koffi 1.3.12 → 2.1.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/CMakeLists.txt +8 -10
- package/ChangeLog.md +48 -16
- package/README.md +6 -0
- package/benchmark/atoi_koffi.js +12 -8
- package/benchmark/atoi_napi.js +12 -8
- package/benchmark/atoi_node_ffi.js +11 -10
- package/benchmark/raylib_cc.cc +12 -9
- package/benchmark/raylib_koffi.js +15 -13
- package/benchmark/raylib_node_ffi.js +15 -13
- package/benchmark/raylib_node_raylib.js +14 -11
- package/build/qemu/2.1.0-beta.1/koffi_darwin_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_linux_arm32hf.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_openbsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_openbsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_win32_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.1/koffi_win32_x64.tar.gz +0 -0
- package/doc/changes.md +160 -1
- package/doc/conf.py +14 -1
- package/doc/contribute.md +0 -1
- package/doc/dist/doctrees/benchmarks.doctree +0 -0
- package/doc/dist/doctrees/changes.doctree +0 -0
- package/doc/dist/doctrees/environment.pickle +0 -0
- package/doc/dist/doctrees/functions.doctree +0 -0
- package/doc/dist/doctrees/index.doctree +0 -0
- package/doc/dist/doctrees/types.doctree +0 -0
- package/doc/dist/html/.buildinfo +1 -1
- package/doc/dist/html/_sources/benchmarks.md.txt +2 -2
- package/doc/dist/html/_sources/changes.md.txt +160 -1
- package/doc/dist/html/_sources/functions.md.txt +17 -13
- package/doc/dist/html/_sources/types.md.txt +87 -35
- package/doc/dist/html/benchmarks.html +7 -3
- package/doc/dist/html/changes.html +241 -14
- package/doc/dist/html/contribute.html +5 -1
- package/doc/dist/html/functions.html +30 -23
- package/doc/dist/html/genindex.html +5 -1
- package/doc/dist/html/index.html +13 -19
- package/doc/dist/html/memory.html +7 -3
- package/doc/dist/html/objects.inv +0 -0
- package/doc/dist/html/platforms.html +6 -2
- package/doc/dist/html/search.html +5 -1
- package/doc/dist/html/searchindex.js +1 -1
- package/doc/dist/html/start.html +5 -1
- package/doc/dist/html/types.html +104 -43
- package/doc/functions.md +139 -15
- package/doc/templates/badges.html +5 -0
- package/doc/types.md +108 -40
- package/package.json +2 -2
- package/qemu/qemu.js +1 -1
- package/qemu/registry/machines.json +5 -5
- package/qemu/registry/sha256sum.txt +16 -16
- package/src/abi_arm32.cc +91 -19
- package/src/abi_arm32_fwd.S +121 -57
- package/src/abi_arm64.cc +91 -19
- package/src/abi_arm64_fwd.S +96 -0
- package/src/abi_arm64_fwd.asm +128 -0
- package/src/abi_riscv64.cc +89 -19
- package/src/abi_riscv64_fwd.S +96 -0
- package/src/abi_x64_sysv.cc +94 -22
- package/src/abi_x64_sysv_fwd.S +96 -0
- package/src/abi_x64_win.cc +89 -19
- package/src/abi_x64_win_fwd.asm +128 -0
- package/src/abi_x86.cc +94 -19
- package/src/abi_x86_fwd.S +96 -0
- package/src/abi_x86_fwd.asm +128 -0
- package/src/call.cc +128 -78
- package/src/call.hh +17 -4
- package/src/ffi.cc +514 -145
- package/src/ffi.hh +30 -9
- package/src/index.js +4 -2
- package/src/parser.cc +19 -44
- package/src/util.cc +160 -27
- package/src/util.hh +7 -2
- package/test/async.js +1 -2
- package/test/callbacks.js +56 -11
- package/test/misc.c +50 -15
- package/test/raylib.js +2 -2
- package/test/sqlite.js +27 -19
- package/test/sync.js +71 -35
- package/vendor/libcc/libcc.cc +18 -5
- package/vendor/libcc/libcc.hh +70 -23
- package/build/qemu/1.3.12/koffi_darwin_arm64.tar.gz +0 -0
- package/build/qemu/1.3.12/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/1.3.12/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/1.3.12/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/1.3.12/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/1.3.12/koffi_linux_arm32hf.tar.gz +0 -0
- package/build/qemu/1.3.12/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/1.3.12/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/1.3.12/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/build/qemu/1.3.12/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/1.3.12/koffi_openbsd_ia32.tar.gz +0 -0
- package/build/qemu/1.3.12/koffi_openbsd_x64.tar.gz +0 -0
- package/build/qemu/1.3.12/koffi_win32_arm64.tar.gz +0 -0
- package/build/qemu/1.3.12/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/1.3.12/koffi_win32_x64.tar.gz +0 -0
package/src/call.cc
CHANGED
|
@@ -40,7 +40,7 @@ CallData::~CallData()
|
|
|
40
40
|
mem->stack = old_stack_mem;
|
|
41
41
|
mem->heap = old_heap_mem;
|
|
42
42
|
|
|
43
|
-
instance->
|
|
43
|
+
instance->temp_trampolines -= used_trampolines;
|
|
44
44
|
instance->temporaries -= mem->temporary;
|
|
45
45
|
|
|
46
46
|
if (!--mem->depth && mem->temporary) {
|
|
@@ -127,9 +127,8 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
|
|
|
127
127
|
RG_ASSERT(IsObject(obj));
|
|
128
128
|
RG_ASSERT(type->primitive == PrimitiveKind::Record);
|
|
129
129
|
|
|
130
|
-
Size
|
|
131
|
-
|
|
132
|
-
for (const RecordMember &member: type->members) {
|
|
130
|
+
for (Size i = 0; i < type->members.len; i++) {
|
|
131
|
+
const RecordMember &member = type->members[i];
|
|
133
132
|
Napi::Value value = obj.Get(member.name);
|
|
134
133
|
|
|
135
134
|
if (RG_UNLIKELY(value.IsUndefined())) {
|
|
@@ -137,9 +136,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
|
|
|
137
136
|
return false;
|
|
138
137
|
}
|
|
139
138
|
|
|
140
|
-
|
|
141
|
-
offset = AlignLen(offset, align);
|
|
142
|
-
|
|
139
|
+
Size offset = realign ? (i * realign) : member.offset;
|
|
143
140
|
uint8_t *dest = origin + offset;
|
|
144
141
|
|
|
145
142
|
switch (member.type->primitive) {
|
|
@@ -257,7 +254,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
|
|
|
257
254
|
*(const char16_t **)dest = str16;
|
|
258
255
|
} break;
|
|
259
256
|
case PrimitiveKind::Pointer: {
|
|
260
|
-
if (CheckValueTag(instance, value, member.type)) {
|
|
257
|
+
if (CheckValueTag(instance, value, member.type->ref.marker)) {
|
|
261
258
|
Napi::External<void> external = value.As<Napi::External<void>>();
|
|
262
259
|
void *ptr = external.Data();
|
|
263
260
|
*(void **)dest = ptr;
|
|
@@ -281,15 +278,15 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
|
|
|
281
278
|
case PrimitiveKind::Array: {
|
|
282
279
|
if (value.IsArray()) {
|
|
283
280
|
Napi::Array array = value.As<Napi::Array>();
|
|
284
|
-
Size len = (Size)member.type->size / member.type->ref->size;
|
|
281
|
+
Size len = (Size)member.type->size / member.type->ref.type->size;
|
|
285
282
|
|
|
286
|
-
if (!PushNormalArray(array, len, member.type->ref, dest, realign))
|
|
283
|
+
if (!PushNormalArray(array, len, member.type->ref.type, dest, realign))
|
|
287
284
|
return false;
|
|
288
285
|
} else if (value.IsTypedArray()) {
|
|
289
286
|
Napi::TypedArray array = value.As<Napi::TypedArray>();
|
|
290
|
-
Size len = (Size)member.type->size / member.type->ref->size;
|
|
287
|
+
Size len = (Size)member.type->size / member.type->ref.type->size;
|
|
291
288
|
|
|
292
|
-
if (!PushTypedArray(array, len, member.type->ref, dest, realign))
|
|
289
|
+
if (!PushTypedArray(array, len, member.type->ref.type, dest, realign))
|
|
293
290
|
return false;
|
|
294
291
|
} else if (value.IsString() && !realign) {
|
|
295
292
|
if (!PushStringArray(value, member.type, dest))
|
|
@@ -323,10 +320,10 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
|
|
|
323
320
|
if (value.IsFunction()) {
|
|
324
321
|
Napi::Function func = value.As<Napi::Function>();
|
|
325
322
|
|
|
326
|
-
ptr = ReserveTrampoline(member.type->proto, func);
|
|
323
|
+
ptr = ReserveTrampoline(member.type->ref.proto, func);
|
|
327
324
|
if (RG_UNLIKELY(!ptr))
|
|
328
325
|
return false;
|
|
329
|
-
} else if (CheckValueTag(instance, value, member.type)) {
|
|
326
|
+
} else if (CheckValueTag(instance, value, member.type->ref.marker)) {
|
|
330
327
|
Napi::External<void> external = value.As<Napi::External<void>>();
|
|
331
328
|
ptr = external.Data();
|
|
332
329
|
} else if (IsNullOrUndefined(value)) {
|
|
@@ -338,9 +335,9 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
|
|
|
338
335
|
|
|
339
336
|
*(void **)dest = ptr;
|
|
340
337
|
} break;
|
|
341
|
-
}
|
|
342
338
|
|
|
343
|
-
|
|
339
|
+
case PrimitiveKind::Prototype: { RG_UNREACHABLE(); } break;
|
|
340
|
+
}
|
|
344
341
|
}
|
|
345
342
|
|
|
346
343
|
return true;
|
|
@@ -460,7 +457,7 @@ bool CallData::PushNormalArray(Napi::Array array, Size len, const TypeInfo *ref,
|
|
|
460
457
|
});
|
|
461
458
|
} break;
|
|
462
459
|
case PrimitiveKind::Pointer: {
|
|
463
|
-
PUSH_ARRAY(CheckValueTag(instance, value, ref) || IsNullOrUndefined(value), ref->name, {
|
|
460
|
+
PUSH_ARRAY(CheckValueTag(instance, value, ref->ref.marker) || IsNullOrUndefined(value), ref->name, {
|
|
464
461
|
if (!IsNullOrUndefined(value)) {
|
|
465
462
|
Napi::External<void> external = value.As<Napi::External<void>>();
|
|
466
463
|
*(void **)dest = external.Data();
|
|
@@ -487,15 +484,15 @@ bool CallData::PushNormalArray(Napi::Array array, Size len, const TypeInfo *ref,
|
|
|
487
484
|
|
|
488
485
|
if (value.IsArray()) {
|
|
489
486
|
Napi::Array array2 = value.As<Napi::Array>();
|
|
490
|
-
Size len2 = (Size)ref->size / ref->ref->size;
|
|
487
|
+
Size len2 = (Size)ref->size / ref->ref.type->size;
|
|
491
488
|
|
|
492
|
-
if (!PushNormalArray(array2, len2, ref->ref, dest, realign))
|
|
489
|
+
if (!PushNormalArray(array2, len2, ref->ref.type, dest, realign))
|
|
493
490
|
return false;
|
|
494
491
|
} else if (value.IsTypedArray()) {
|
|
495
492
|
Napi::TypedArray array2 = value.As<Napi::TypedArray>();
|
|
496
|
-
Size len2 = (Size)ref->size / ref->ref->size;
|
|
493
|
+
Size len2 = (Size)ref->size / ref->ref.type->size;
|
|
497
494
|
|
|
498
|
-
if (!PushTypedArray(array2, len2, ref->ref, dest, realign))
|
|
495
|
+
if (!PushTypedArray(array2, len2, ref->ref.type, dest, realign))
|
|
499
496
|
return false;
|
|
500
497
|
} else if (value.IsString() && !realign) {
|
|
501
498
|
if (!PushStringArray(value, ref, dest))
|
|
@@ -534,10 +531,10 @@ bool CallData::PushNormalArray(Napi::Array array, Size len, const TypeInfo *ref,
|
|
|
534
531
|
if (value.IsFunction()) {
|
|
535
532
|
Napi::Function func = value.As<Napi::Function>();
|
|
536
533
|
|
|
537
|
-
ptr = ReserveTrampoline(ref->proto, func);
|
|
534
|
+
ptr = ReserveTrampoline(ref->ref.proto, func);
|
|
538
535
|
if (RG_UNLIKELY(!ptr))
|
|
539
536
|
return false;
|
|
540
|
-
} else if (CheckValueTag(instance, value, ref)) {
|
|
537
|
+
} else if (CheckValueTag(instance, value, ref->ref.marker)) {
|
|
541
538
|
Napi::External<void> external = value.As<Napi::External<void>>();
|
|
542
539
|
ptr = external.Data();
|
|
543
540
|
} else if (IsNullOrUndefined(value)) {
|
|
@@ -552,6 +549,8 @@ bool CallData::PushNormalArray(Napi::Array array, Size len, const TypeInfo *ref,
|
|
|
552
549
|
offset += ref->size;
|
|
553
550
|
}
|
|
554
551
|
} break;
|
|
552
|
+
|
|
553
|
+
case PrimitiveKind::Prototype: { RG_UNREACHABLE(); } break;
|
|
555
554
|
}
|
|
556
555
|
|
|
557
556
|
#undef PUSH_ARRAY
|
|
@@ -568,24 +567,26 @@ bool CallData::PushTypedArray(Napi::TypedArray array, Size len, const TypeInfo *
|
|
|
568
567
|
return false;
|
|
569
568
|
}
|
|
570
569
|
|
|
571
|
-
Size offset = 0;
|
|
572
570
|
const uint8_t *buf = (const uint8_t *)array.ArrayBuffer().Data();
|
|
573
571
|
|
|
574
|
-
if (RG_UNLIKELY(array.TypedArrayType() != GetTypedArrayType(ref)
|
|
572
|
+
if (RG_UNLIKELY(array.TypedArrayType() != GetTypedArrayType(ref) &&
|
|
573
|
+
ref != instance->void_type)) {
|
|
575
574
|
ThrowError<Napi::TypeError>(env, "Cannot use %1 value for %2 array", GetValueType(instance, array), ref->name);
|
|
576
575
|
return false;
|
|
577
576
|
}
|
|
578
577
|
|
|
579
578
|
if (realign) {
|
|
579
|
+
Size offset = 0;
|
|
580
|
+
Size size = (Size)array.ElementSize();
|
|
581
|
+
|
|
580
582
|
for (uint32_t i = 0; i < len; i++) {
|
|
581
|
-
|
|
582
|
-
offset = AlignLen(offset, align);
|
|
583
|
+
offset = AlignLen(offset, realign);
|
|
583
584
|
|
|
584
585
|
uint8_t *dest = origin + offset;
|
|
586
|
+
const uint8_t *src = buf + i * size;
|
|
585
587
|
|
|
586
|
-
memcpy(dest,
|
|
587
|
-
|
|
588
|
-
offset += ref->size;
|
|
588
|
+
memcpy(dest, src, size);
|
|
589
|
+
offset += size;
|
|
589
590
|
}
|
|
590
591
|
} else {
|
|
591
592
|
memcpy_safe(origin, buf, (size_t)array.ByteLength());
|
|
@@ -601,7 +602,7 @@ bool CallData::PushStringArray(Napi::Value obj, const TypeInfo *type, uint8_t *o
|
|
|
601
602
|
|
|
602
603
|
size_t encoded = 0;
|
|
603
604
|
|
|
604
|
-
switch (type->ref->primitive) {
|
|
605
|
+
switch (type->ref.type->primitive) {
|
|
605
606
|
case PrimitiveKind::Int8: {
|
|
606
607
|
napi_status status = napi_get_value_string_utf8(env, obj, (char *)origin, type->size, &encoded);
|
|
607
608
|
RG_ASSERT(status == napi_ok);
|
|
@@ -614,7 +615,7 @@ bool CallData::PushStringArray(Napi::Value obj, const TypeInfo *type, uint8_t *o
|
|
|
614
615
|
} break;
|
|
615
616
|
|
|
616
617
|
default: {
|
|
617
|
-
ThrowError<Napi::TypeError>(env, "Strings cannot be converted to %1 array", type->ref->name);
|
|
618
|
+
ThrowError<Napi::TypeError>(env, "Strings cannot be converted to %1 array", type->ref.type->name);
|
|
618
619
|
return false;
|
|
619
620
|
} break;
|
|
620
621
|
}
|
|
@@ -626,6 +627,16 @@ bool CallData::PushStringArray(Napi::Value obj, const TypeInfo *type, uint8_t *o
|
|
|
626
627
|
|
|
627
628
|
bool CallData::PushPointer(Napi::Value value, const ParameterInfo ¶m, void **out_ptr)
|
|
628
629
|
{
|
|
630
|
+
const TypeInfo *type = param.type;
|
|
631
|
+
|
|
632
|
+
if (CheckValueTag(instance, value, &CastMarker)) {
|
|
633
|
+
Napi::External<ValueCast> external = value.As<Napi::External<ValueCast>>();
|
|
634
|
+
ValueCast *cast = external.Data();
|
|
635
|
+
|
|
636
|
+
value = cast->ref.Value();
|
|
637
|
+
type = cast->type;
|
|
638
|
+
}
|
|
639
|
+
|
|
629
640
|
switch (value.Type()) {
|
|
630
641
|
case napi_undefined:
|
|
631
642
|
case napi_null: {
|
|
@@ -634,7 +645,11 @@ bool CallData::PushPointer(Napi::Value value, const ParameterInfo ¶m, void *
|
|
|
634
645
|
} break;
|
|
635
646
|
|
|
636
647
|
case napi_external: {
|
|
637
|
-
|
|
648
|
+
RG_ASSERT(type->primitive == PrimitiveKind::Pointer);
|
|
649
|
+
|
|
650
|
+
if (RG_UNLIKELY(!CheckValueTag(instance, value, type->ref.marker) &&
|
|
651
|
+
!CheckValueTag(instance, value, instance->void_type) &&
|
|
652
|
+
type->ref.type != instance->void_type))
|
|
638
653
|
goto unexpected;
|
|
639
654
|
|
|
640
655
|
*out_ptr = value.As<Napi::External<uint8_t>>().Data();
|
|
@@ -648,12 +663,12 @@ bool CallData::PushPointer(Napi::Value value, const ParameterInfo ¶m, void *
|
|
|
648
663
|
Napi::Array array = value.As<Napi::Array>();
|
|
649
664
|
|
|
650
665
|
Size len = (Size)array.Length();
|
|
651
|
-
Size size = len *
|
|
666
|
+
Size size = len * type->ref.type->size;
|
|
652
667
|
|
|
653
668
|
ptr = AllocHeap(size, 16);
|
|
654
669
|
|
|
655
670
|
if (param.directions & 1) {
|
|
656
|
-
if (!PushNormalArray(array, len,
|
|
671
|
+
if (!PushNormalArray(array, len, type->ref.type, ptr))
|
|
657
672
|
return false;
|
|
658
673
|
} else {
|
|
659
674
|
memset(ptr, 0, size);
|
|
@@ -667,27 +682,28 @@ bool CallData::PushPointer(Napi::Value value, const ParameterInfo ¶m, void *
|
|
|
667
682
|
ptr = AllocHeap(size, 16);
|
|
668
683
|
|
|
669
684
|
if (param.directions & 1) {
|
|
670
|
-
if (!PushTypedArray(array, len,
|
|
685
|
+
if (!PushTypedArray(array, len, type->ref.type, ptr))
|
|
671
686
|
return false;
|
|
672
687
|
} else {
|
|
673
|
-
if (RG_UNLIKELY(array.TypedArrayType() != GetTypedArrayType(
|
|
674
|
-
|
|
688
|
+
if (RG_UNLIKELY(array.TypedArrayType() != GetTypedArrayType(type->ref.type) &&
|
|
689
|
+
type->ref.type != instance->void_type)) {
|
|
690
|
+
ThrowError<Napi::TypeError>(env, "Cannot use %1 value for %2 array", GetValueType(instance, array), type->ref.type->name);
|
|
675
691
|
return false;
|
|
676
692
|
}
|
|
677
693
|
|
|
678
694
|
memset(ptr, 0, size);
|
|
679
695
|
}
|
|
680
|
-
} else if (RG_LIKELY(
|
|
696
|
+
} else if (RG_LIKELY(type->ref.type->primitive == PrimitiveKind::Record)) {
|
|
681
697
|
Napi::Object obj = value.As<Napi::Object>();
|
|
682
698
|
RG_ASSERT(IsObject(value));
|
|
683
699
|
|
|
684
|
-
ptr = AllocHeap(
|
|
700
|
+
ptr = AllocHeap(type->ref.type->size, 16);
|
|
685
701
|
|
|
686
702
|
if (param.directions & 1) {
|
|
687
|
-
if (!PushObject(obj,
|
|
703
|
+
if (!PushObject(obj, type->ref.type, ptr))
|
|
688
704
|
return false;
|
|
689
705
|
} else {
|
|
690
|
-
memset(ptr, 0,
|
|
706
|
+
memset(ptr, 0, type->size);
|
|
691
707
|
}
|
|
692
708
|
} else {
|
|
693
709
|
goto unexpected;
|
|
@@ -700,7 +716,7 @@ bool CallData::PushPointer(Napi::Value value, const ParameterInfo ¶m, void *
|
|
|
700
716
|
RG_ASSERT(status == napi_ok);
|
|
701
717
|
|
|
702
718
|
out->ptr = ptr;
|
|
703
|
-
out->type =
|
|
719
|
+
out->type = type->ref.type;
|
|
704
720
|
}
|
|
705
721
|
|
|
706
722
|
*out_ptr = ptr;
|
|
@@ -711,7 +727,7 @@ bool CallData::PushPointer(Napi::Value value, const ParameterInfo ¶m, void *
|
|
|
711
727
|
}
|
|
712
728
|
|
|
713
729
|
unexpected:
|
|
714
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected %3", GetValueType(instance, value), param.offset + 1,
|
|
730
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected %3", GetValueType(instance, value), param.offset + 1, type->name);
|
|
715
731
|
return false;
|
|
716
732
|
}
|
|
717
733
|
|
|
@@ -741,27 +757,34 @@ void CallData::PopOutArguments()
|
|
|
741
757
|
Napi::Object obj(env, value);
|
|
742
758
|
PopObject(obj, out.ptr, out.type);
|
|
743
759
|
}
|
|
760
|
+
|
|
761
|
+
if (out.type->dispose) {
|
|
762
|
+
out.type->dispose(env, out.type, out.ptr);
|
|
763
|
+
}
|
|
744
764
|
}
|
|
745
765
|
}
|
|
746
766
|
|
|
747
767
|
void *CallData::ReserveTrampoline(const FunctionInfo *proto, Napi::Function func)
|
|
748
768
|
{
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
if (RG_UNLIKELY(idx >= MaxTrampolines)) {
|
|
752
|
-
ThrowError<Napi::Error>(env, "Too many callbacks are in use (max = %1)", MaxTrampolines);
|
|
769
|
+
if (RG_UNLIKELY(instance->temp_trampolines >= MaxTrampolines)) {
|
|
770
|
+
ThrowError<Napi::Error>(env, "Too many temporary callbacks are in use (max = %1)", MaxTrampolines);
|
|
753
771
|
return nullptr;
|
|
754
772
|
}
|
|
755
773
|
|
|
756
|
-
|
|
757
|
-
|
|
774
|
+
int idx = instance->next_trampoline;
|
|
775
|
+
|
|
776
|
+
instance->next_trampoline = (int16_t)((instance->next_trampoline + 1) % MaxTrampolines);
|
|
777
|
+
instance->temp_trampolines++;
|
|
778
|
+
used_trampolines++;
|
|
758
779
|
|
|
759
|
-
instance->trampolines[idx]
|
|
760
|
-
instance->trampolines[idx].func.Reset(func, 1);
|
|
761
|
-
instance->trampolines[idx].generation = mem->generation;
|
|
780
|
+
TrampolineInfo *trampoline = &instance->trampolines[idx];
|
|
762
781
|
|
|
763
|
-
|
|
764
|
-
|
|
782
|
+
trampoline->proto = proto;
|
|
783
|
+
trampoline->func.Reset(func, 1);
|
|
784
|
+
trampoline->generation = (int32_t)mem->generation;
|
|
785
|
+
|
|
786
|
+
void *ptr = GetTrampoline(idx, proto);
|
|
787
|
+
return ptr;
|
|
765
788
|
}
|
|
766
789
|
|
|
767
790
|
void CallData::PopObject(Napi::Object obj, const uint8_t *origin, const TypeInfo *type, int16_t realign)
|
|
@@ -771,12 +794,10 @@ void CallData::PopObject(Napi::Object obj, const uint8_t *origin, const TypeInfo
|
|
|
771
794
|
|
|
772
795
|
RG_ASSERT(type->primitive == PrimitiveKind::Record);
|
|
773
796
|
|
|
774
|
-
Size
|
|
775
|
-
|
|
776
|
-
for (const RecordMember &member: type->members) {
|
|
777
|
-
int16_t align = std::max(realign, member.align);
|
|
778
|
-
offset = AlignLen(offset, align);
|
|
797
|
+
for (Size i = 0; i < type->members.len; i++) {
|
|
798
|
+
const RecordMember &member = type->members[i];
|
|
779
799
|
|
|
800
|
+
Size offset = realign ? (i * realign) : member.offset;
|
|
780
801
|
const uint8_t *src = origin + offset;
|
|
781
802
|
|
|
782
803
|
switch (member.type->primitive) {
|
|
@@ -821,10 +842,18 @@ void CallData::PopObject(Napi::Object obj, const uint8_t *origin, const TypeInfo
|
|
|
821
842
|
case PrimitiveKind::String: {
|
|
822
843
|
const char *str = *(const char **)src;
|
|
823
844
|
obj.Set(member.name, str ? Napi::String::New(env, str) : env.Null());
|
|
845
|
+
|
|
846
|
+
if (member.type->dispose) {
|
|
847
|
+
member.type->dispose(env, member.type, str);
|
|
848
|
+
}
|
|
824
849
|
} break;
|
|
825
850
|
case PrimitiveKind::String16: {
|
|
826
851
|
const char16_t *str16 = *(const char16_t **)src;
|
|
827
852
|
obj.Set(member.name, str16 ? Napi::String::New(env, str16) : env.Null());
|
|
853
|
+
|
|
854
|
+
if (member.type->dispose) {
|
|
855
|
+
member.type->dispose(env, member.type, str16);
|
|
856
|
+
}
|
|
828
857
|
} break;
|
|
829
858
|
case PrimitiveKind::Pointer:
|
|
830
859
|
case PrimitiveKind::Callback: {
|
|
@@ -832,12 +861,16 @@ void CallData::PopObject(Napi::Object obj, const uint8_t *origin, const TypeInfo
|
|
|
832
861
|
|
|
833
862
|
if (ptr2) {
|
|
834
863
|
Napi::External<void> external = Napi::External<void>::New(env, ptr2);
|
|
835
|
-
SetValueTag(instance, external, member.type);
|
|
864
|
+
SetValueTag(instance, external, member.type->ref.marker);
|
|
836
865
|
|
|
837
866
|
obj.Set(member.name, external);
|
|
838
867
|
} else {
|
|
839
868
|
obj.Set(member.name, env.Null());
|
|
840
869
|
}
|
|
870
|
+
|
|
871
|
+
if (member.type->dispose) {
|
|
872
|
+
member.type->dispose(env, member.type, ptr2);
|
|
873
|
+
}
|
|
841
874
|
} break;
|
|
842
875
|
case PrimitiveKind::Record: {
|
|
843
876
|
Napi::Object obj2 = PopObject(src, member.type, realign);
|
|
@@ -855,9 +888,9 @@ void CallData::PopObject(Napi::Object obj, const uint8_t *origin, const TypeInfo
|
|
|
855
888
|
double d = *(double *)src;
|
|
856
889
|
obj.Set(member.name, Napi::Number::New(env, d));
|
|
857
890
|
} break;
|
|
858
|
-
}
|
|
859
891
|
|
|
860
|
-
|
|
892
|
+
case PrimitiveKind::Prototype: { RG_UNREACHABLE(); } break;
|
|
893
|
+
}
|
|
861
894
|
}
|
|
862
895
|
}
|
|
863
896
|
|
|
@@ -938,12 +971,20 @@ void CallData::PopNormalArray(Napi::Array array, const uint8_t *origin, const Ty
|
|
|
938
971
|
POP_ARRAY({
|
|
939
972
|
const char *str = *(const char **)src;
|
|
940
973
|
array.Set(i, str ? Napi::String::New(env, str) : env.Null());
|
|
974
|
+
|
|
975
|
+
if (ref->dispose) {
|
|
976
|
+
ref->dispose(env, ref, str);
|
|
977
|
+
}
|
|
941
978
|
});
|
|
942
979
|
} break;
|
|
943
980
|
case PrimitiveKind::String16: {
|
|
944
981
|
POP_ARRAY({
|
|
945
982
|
const char16_t *str16 = *(const char16_t **)src;
|
|
946
983
|
array.Set(i, str16 ? Napi::String::New(env, str16) : env.Null());
|
|
984
|
+
|
|
985
|
+
if (ref->dispose) {
|
|
986
|
+
ref->dispose(env, ref, str16);
|
|
987
|
+
}
|
|
947
988
|
});
|
|
948
989
|
} break;
|
|
949
990
|
case PrimitiveKind::Pointer:
|
|
@@ -953,12 +994,16 @@ void CallData::PopNormalArray(Napi::Array array, const uint8_t *origin, const Ty
|
|
|
953
994
|
|
|
954
995
|
if (ptr2) {
|
|
955
996
|
Napi::External<void> external = Napi::External<void>::New(env, ptr2);
|
|
956
|
-
SetValueTag(instance, external, ref);
|
|
997
|
+
SetValueTag(instance, external, ref->ref.marker);
|
|
957
998
|
|
|
958
999
|
array.Set(i, external);
|
|
959
1000
|
} else {
|
|
960
1001
|
array.Set(i, env.Null());
|
|
961
1002
|
}
|
|
1003
|
+
|
|
1004
|
+
if (ref->dispose) {
|
|
1005
|
+
ref->dispose(env, ref, ptr2);
|
|
1006
|
+
}
|
|
962
1007
|
});
|
|
963
1008
|
} break;
|
|
964
1009
|
case PrimitiveKind::Record: {
|
|
@@ -975,6 +1020,8 @@ void CallData::PopNormalArray(Napi::Array array, const uint8_t *origin, const Ty
|
|
|
975
1020
|
} break;
|
|
976
1021
|
case PrimitiveKind::Float32: { POP_NUMBER_ARRAY(float); } break;
|
|
977
1022
|
case PrimitiveKind::Float64: { POP_NUMBER_ARRAY(double); } break;
|
|
1023
|
+
|
|
1024
|
+
case PrimitiveKind::Prototype: { RG_UNREACHABLE(); } break;
|
|
978
1025
|
}
|
|
979
1026
|
|
|
980
1027
|
#undef POP_NUMBER_ARRAY
|
|
@@ -984,24 +1031,25 @@ void CallData::PopNormalArray(Napi::Array array, const uint8_t *origin, const Ty
|
|
|
984
1031
|
void CallData::PopTypedArray(Napi::TypedArray array, const uint8_t *origin, const TypeInfo *ref, int16_t realign)
|
|
985
1032
|
{
|
|
986
1033
|
RG_ASSERT(array.IsTypedArray());
|
|
987
|
-
RG_ASSERT(GetTypedArrayType(ref) == array.TypedArrayType()
|
|
1034
|
+
RG_ASSERT(GetTypedArrayType(ref) == array.TypedArrayType() ||
|
|
1035
|
+
ref == instance->void_type);
|
|
988
1036
|
|
|
989
1037
|
uint8_t *buf = (uint8_t *)array.ArrayBuffer().Data();
|
|
990
1038
|
|
|
991
1039
|
if (realign) {
|
|
992
1040
|
Size offset = 0;
|
|
993
1041
|
Size len = (Size)array.ElementLength();
|
|
1042
|
+
Size size = (Size)array.ElementSize();
|
|
994
1043
|
|
|
995
1044
|
for (Size i = 0; i < len; i++) {
|
|
996
|
-
|
|
997
|
-
offset = AlignLen(offset, align);
|
|
1045
|
+
offset = AlignLen(offset, realign);
|
|
998
1046
|
|
|
999
|
-
uint8_t *dest = buf + i *
|
|
1047
|
+
uint8_t *dest = buf + i * size;
|
|
1000
1048
|
const uint8_t *src = origin + offset;
|
|
1001
1049
|
|
|
1002
|
-
memcpy(dest, src,
|
|
1050
|
+
memcpy(dest, src, size);
|
|
1003
1051
|
|
|
1004
|
-
offset +=
|
|
1052
|
+
offset += size;
|
|
1005
1053
|
}
|
|
1006
1054
|
} else {
|
|
1007
1055
|
memcpy_safe(buf, origin, (size_t)array.ByteLength());
|
|
@@ -1012,7 +1060,7 @@ Napi::Value CallData::PopArray(const uint8_t *origin, const TypeInfo *type, int1
|
|
|
1012
1060
|
{
|
|
1013
1061
|
RG_ASSERT(type->primitive == PrimitiveKind::Array);
|
|
1014
1062
|
|
|
1015
|
-
uint32_t len = type->size / type->ref->size;
|
|
1063
|
+
uint32_t len = type->size / type->ref.type->size;
|
|
1016
1064
|
Size offset = 0;
|
|
1017
1065
|
|
|
1018
1066
|
#define POP_ARRAY(SetCode) \
|
|
@@ -1020,14 +1068,14 @@ Napi::Value CallData::PopArray(const uint8_t *origin, const TypeInfo *type, int1
|
|
|
1020
1068
|
Napi::Array array = Napi::Array::New(env); \
|
|
1021
1069
|
\
|
|
1022
1070
|
for (uint32_t i = 0; i < len; i++) { \
|
|
1023
|
-
int16_t align = std::max(realign, type->ref->align); \
|
|
1071
|
+
int16_t align = std::max(realign, type->ref.type->align); \
|
|
1024
1072
|
offset = AlignLen(offset, align); \
|
|
1025
1073
|
\
|
|
1026
1074
|
const uint8_t *src = origin + offset; \
|
|
1027
1075
|
\
|
|
1028
1076
|
SetCode \
|
|
1029
1077
|
\
|
|
1030
|
-
offset += type->ref->size; \
|
|
1078
|
+
offset += type->ref.type->size; \
|
|
1031
1079
|
} \
|
|
1032
1080
|
\
|
|
1033
1081
|
return array; \
|
|
@@ -1041,13 +1089,13 @@ Napi::Value CallData::PopArray(const uint8_t *origin, const TypeInfo *type, int1
|
|
|
1041
1089
|
}); \
|
|
1042
1090
|
} else { \
|
|
1043
1091
|
Napi::TypedArrayType array = Napi::TypedArrayType::New(env, len); \
|
|
1044
|
-
PopTypedArray(array, origin, type->ref, realign); \
|
|
1092
|
+
PopTypedArray(array, origin, type->ref.type, realign); \
|
|
1045
1093
|
\
|
|
1046
1094
|
return array; \
|
|
1047
1095
|
} \
|
|
1048
1096
|
} while (false)
|
|
1049
1097
|
|
|
1050
|
-
switch (type->ref->primitive) {
|
|
1098
|
+
switch (type->ref.type->primitive) {
|
|
1051
1099
|
case PrimitiveKind::Void: { RG_UNREACHABLE(); } break;
|
|
1052
1100
|
|
|
1053
1101
|
case PrimitiveKind::Bool: {
|
|
@@ -1117,7 +1165,7 @@ Napi::Value CallData::PopArray(const uint8_t *origin, const TypeInfo *type, int1
|
|
|
1117
1165
|
|
|
1118
1166
|
if (ptr2) {
|
|
1119
1167
|
Napi::External<void> external = Napi::External<void>::New(env, ptr2);
|
|
1120
|
-
SetValueTag(instance, external, type->ref);
|
|
1168
|
+
SetValueTag(instance, external, type->ref.type->ref.marker);
|
|
1121
1169
|
|
|
1122
1170
|
array.Set(i, external);
|
|
1123
1171
|
} else {
|
|
@@ -1127,18 +1175,20 @@ Napi::Value CallData::PopArray(const uint8_t *origin, const TypeInfo *type, int1
|
|
|
1127
1175
|
} break;
|
|
1128
1176
|
case PrimitiveKind::Record: {
|
|
1129
1177
|
POP_ARRAY({
|
|
1130
|
-
Napi::Object obj = PopObject(src, type->ref, realign);
|
|
1178
|
+
Napi::Object obj = PopObject(src, type->ref.type, realign);
|
|
1131
1179
|
array.Set(i, obj);
|
|
1132
1180
|
});
|
|
1133
1181
|
} break;
|
|
1134
1182
|
case PrimitiveKind::Array: {
|
|
1135
1183
|
POP_ARRAY({
|
|
1136
|
-
Napi::Value value = PopArray(src, type->ref, realign);
|
|
1184
|
+
Napi::Value value = PopArray(src, type->ref.type, realign);
|
|
1137
1185
|
array.Set(i, value);
|
|
1138
1186
|
});
|
|
1139
1187
|
} break;
|
|
1140
1188
|
case PrimitiveKind::Float32: { POP_NUMBER_ARRAY(Float32Array, float); } break;
|
|
1141
1189
|
case PrimitiveKind::Float64: { POP_NUMBER_ARRAY(Float64Array, double); } break;
|
|
1190
|
+
|
|
1191
|
+
case PrimitiveKind::Prototype: { RG_UNREACHABLE(); } break;
|
|
1142
1192
|
}
|
|
1143
1193
|
|
|
1144
1194
|
#undef POP_NUMBER_ARRAY
|
package/src/call.hh
CHANGED
|
@@ -42,7 +42,7 @@ class alignas(8) CallData {
|
|
|
42
42
|
Span<uint8_t> old_stack_mem;
|
|
43
43
|
Span<uint8_t> old_heap_mem;
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
int16_t used_trampolines = 0;
|
|
46
46
|
|
|
47
47
|
LocalArray<OutArgument, MaxOutParameters> out_arguments;
|
|
48
48
|
|
|
@@ -71,9 +71,21 @@ public:
|
|
|
71
71
|
CallData(Napi::Env env, InstanceData *instance, const FunctionInfo *func, InstanceMemory *mem);
|
|
72
72
|
~CallData();
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
#ifdef UNITY_BUILD
|
|
75
|
+
#ifdef _MSC_VER
|
|
76
|
+
#define INLINE_IF_UNITY __forceinline
|
|
77
|
+
#else
|
|
78
|
+
#define INLINE_IF_UNITY __attribute__((always_inline)) inline
|
|
79
|
+
#endif
|
|
80
|
+
#else
|
|
81
|
+
#define INLINE_IF_UNITY
|
|
82
|
+
#endif
|
|
83
|
+
|
|
84
|
+
INLINE_IF_UNITY bool Prepare(const Napi::CallbackInfo &info);
|
|
85
|
+
INLINE_IF_UNITY void Execute();
|
|
86
|
+
INLINE_IF_UNITY Napi::Value Complete();
|
|
87
|
+
|
|
88
|
+
#undef INLINE_IF_UNITY
|
|
77
89
|
|
|
78
90
|
void Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegisters *out_reg);
|
|
79
91
|
|
|
@@ -103,6 +115,7 @@ private:
|
|
|
103
115
|
|
|
104
116
|
void *ReserveTrampoline(const FunctionInfo *proto, Napi::Function func);
|
|
105
117
|
};
|
|
118
|
+
RG_STATIC_ASSERT(MaxTrampolines <= 32);
|
|
106
119
|
|
|
107
120
|
template <typename T>
|
|
108
121
|
inline bool CallData::AllocStack(Size size, Size align, T **out_ptr)
|