koffi 3.0.0 → 3.0.2
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 +20 -1
- package/README.md +5 -4
- package/cnoke.cjs +10 -10
- package/doc/benchmarks.md +24 -47
- package/doc/callbacks.md +4 -13
- package/doc/contribute.md +4 -4
- package/doc/index.md +3 -2
- package/doc/migration.md +100 -0
- package/doc/start.md +7 -5
- package/index.d.ts +53 -5
- package/index.js +2 -1
- package/indirect.js +2 -1
- package/package.json +20 -18
- package/src/koffi/CMakeLists.txt +20 -12
- package/src/koffi/index.cjs +92 -129
- package/src/koffi/index.js +128 -113
- package/src/koffi/indirect.cjs +91 -128
- package/src/koffi/indirect.js +129 -40
- package/src/koffi/src/abi/arm64.cc +30 -29
- package/src/koffi/src/abi/riscv64.cc +30 -29
- package/src/koffi/src/abi/x64sysv.cc +26 -25
- package/src/koffi/src/abi/x64win.cc +64 -63
- package/src/koffi/src/abi/x86.cc +67 -65
- package/src/koffi/src/call.cc +210 -99
- package/src/koffi/src/call.hh +2 -1
- package/src/koffi/src/ffi.cc +403 -237
- package/src/koffi/src/ffi.hh +46 -7
- package/src/koffi/src/parser.cc +3 -1
- package/src/koffi/src/primitives.inc +1 -4
- package/src/koffi/src/static.cjs +122 -0
- package/src/koffi/src/static.js +122 -0
- package/src/koffi/src/type.cc +715 -0
- package/src/koffi/src/type.hh +71 -0
- package/src/koffi/src/util.cc +189 -1120
- package/src/koffi/src/util.hh +85 -125
- package/src/koffi/src/uv.cc +16 -10
- package/src/koffi/src/uv.hh +2 -1
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
#include "lib/native/base/base.hh"
|
|
7
7
|
#include "../ffi.hh"
|
|
8
8
|
#include "../call.hh"
|
|
9
|
+
#include "../type.hh"
|
|
9
10
|
#include "../util.hh"
|
|
10
11
|
|
|
11
12
|
#include <napi.h>
|
|
@@ -59,14 +60,14 @@ enum class AbiOpcode {
|
|
|
59
60
|
RunAggregateDD,
|
|
60
61
|
RunAggregateGD,
|
|
61
62
|
RunAggregateDG,
|
|
62
|
-
|
|
63
|
+
RunAggregateMem,
|
|
63
64
|
#define PRIMITIVE(Name) Run ## Name ## X,
|
|
64
65
|
#include "../primitives.inc"
|
|
65
66
|
RunAggregateGGX,
|
|
66
67
|
RunAggregateDDX,
|
|
67
68
|
RunAggregateGDX,
|
|
68
69
|
RunAggregateDGX,
|
|
69
|
-
|
|
70
|
+
RunAggregateMemX,
|
|
70
71
|
Yield,
|
|
71
72
|
CallGG,
|
|
72
73
|
CallF,
|
|
@@ -83,7 +84,7 @@ enum class AbiOpcode {
|
|
|
83
84
|
#define PRIMITIVE(Name) Return ## Name,
|
|
84
85
|
#include "../primitives.inc"
|
|
85
86
|
ReturnAggregateReg,
|
|
86
|
-
|
|
87
|
+
ReturnAggregateMem
|
|
87
88
|
};
|
|
88
89
|
|
|
89
90
|
enum class AbiMethod {
|
|
@@ -452,12 +453,12 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
|
|
|
452
453
|
case PrimitiveKind::Union: {
|
|
453
454
|
switch (func->ret.abi.method) {
|
|
454
455
|
case AbiMethod::Stack: {
|
|
455
|
-
AbiOpcode run = func->forward_fp ? AbiOpcode::
|
|
456
|
+
AbiOpcode run = func->forward_fp ? AbiOpcode::RunAggregateMemX : AbiOpcode::RunAggregateMem;
|
|
456
457
|
AbiOpcode call = func->forward_fp ? AbiOpcode::CallStackX : AbiOpcode::CallStack;
|
|
457
458
|
|
|
458
459
|
func->sync.Append({ .op = Code2Op(run), .a = (int32_t)func->ret.type->size, .type = func->ret.type });
|
|
459
460
|
func->async.Append({ .op = Code2Op(call), .a = (int32_t)func->ret.type->size });
|
|
460
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
461
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateMem), .type = func->ret.type });
|
|
461
462
|
|
|
462
463
|
// Allocate stack space for return value
|
|
463
464
|
func->stk_size += AlignLen(func->ret.type->size, 16);
|
|
@@ -801,25 +802,25 @@ namespace {
|
|
|
801
802
|
OP(RunPrototype) { K_UNREACHABLE(); return call->env.Null(); }
|
|
802
803
|
OP(RunAggregateGG) {
|
|
803
804
|
auto ret = WRAP(ForwardCallGG(call->native, base, &call->saved_sp));
|
|
804
|
-
return DecodeObject(call->
|
|
805
|
+
return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
|
|
805
806
|
}
|
|
806
807
|
OP(RunAggregateDD) {
|
|
807
808
|
auto ret = WRAP(ForwardCallDD(call->native, base, &call->saved_sp));
|
|
808
|
-
return DecodeObject(call->
|
|
809
|
+
return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
|
|
809
810
|
}
|
|
810
811
|
OP(RunAggregateGD) {
|
|
811
812
|
auto ret = WRAP(ForwardCallGD(call->native, base, &call->saved_sp));
|
|
812
|
-
return DecodeObject(call->
|
|
813
|
+
return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
|
|
813
814
|
}
|
|
814
815
|
OP(RunAggregateDG) {
|
|
815
816
|
auto ret = WRAP(ForwardCallDG(call->native, base, &call->saved_sp));
|
|
816
|
-
return DecodeObject(call->
|
|
817
|
+
return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
|
|
817
818
|
}
|
|
818
|
-
OP(
|
|
819
|
+
OP(RunAggregateMem) {
|
|
819
820
|
uint8_t *ptr = call->AllocHeap(inst->a);
|
|
820
821
|
*(uint8_t **)base = ptr;
|
|
821
822
|
WRAP(ForwardCallGG(call->native, base, &call->saved_sp).rax);
|
|
822
|
-
return DecodeObject(call->
|
|
823
|
+
return DecodeObject(call->instance, ptr, inst->type);
|
|
823
824
|
}
|
|
824
825
|
OP(RunVoidX) {
|
|
825
826
|
WRAP(ForwardCallGGX(call->native, base, &call->saved_sp));
|
|
@@ -885,25 +886,25 @@ namespace {
|
|
|
885
886
|
OP(RunPrototypeX) { K_UNREACHABLE(); return call->env.Null(); }
|
|
886
887
|
OP(RunAggregateGGX) {
|
|
887
888
|
auto ret = WRAP(ForwardCallGGX(call->native, base, &call->saved_sp));
|
|
888
|
-
return DecodeObject(call->
|
|
889
|
+
return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
|
|
889
890
|
}
|
|
890
891
|
OP(RunAggregateDDX) {
|
|
891
892
|
auto ret = WRAP(ForwardCallDDX(call->native, base, &call->saved_sp));
|
|
892
|
-
return DecodeObject(call->
|
|
893
|
+
return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
|
|
893
894
|
}
|
|
894
895
|
OP(RunAggregateGDX) {
|
|
895
896
|
auto ret = WRAP(ForwardCallGDX(call->native, base, &call->saved_sp));
|
|
896
|
-
return DecodeObject(call->
|
|
897
|
+
return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
|
|
897
898
|
}
|
|
898
899
|
OP(RunAggregateDGX) {
|
|
899
900
|
auto ret = WRAP(ForwardCallDGX(call->native, base, &call->saved_sp));
|
|
900
|
-
return DecodeObject(call->
|
|
901
|
+
return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
|
|
901
902
|
}
|
|
902
|
-
OP(
|
|
903
|
+
OP(RunAggregateMemX) {
|
|
903
904
|
uint8_t *ptr = call->AllocHeap(inst->a);
|
|
904
905
|
*(uint8_t **)base = ptr;
|
|
905
906
|
WRAP(ForwardCallGGX(call->native, base, &call->saved_sp).rax);
|
|
906
|
-
return DecodeObject(call->
|
|
907
|
+
return DecodeObject(call->instance, ptr, inst->type);
|
|
907
908
|
}
|
|
908
909
|
|
|
909
910
|
#undef DISPOSE
|
|
@@ -1020,10 +1021,10 @@ namespace {
|
|
|
1020
1021
|
return Napi::Number::New(call->env, d);
|
|
1021
1022
|
}
|
|
1022
1023
|
OP(ReturnPrototype) { K_UNREACHABLE(); return call->env.Null(); }
|
|
1023
|
-
OP(ReturnAggregateReg) { return DecodeObject(call->
|
|
1024
|
-
OP(
|
|
1024
|
+
OP(ReturnAggregateReg) { return DecodeObject(call->instance, base, inst->type); }
|
|
1025
|
+
OP(ReturnAggregateMem) {
|
|
1025
1026
|
uint64_t rax = *(uint64_t *)base;
|
|
1026
|
-
return DecodeObject(call->
|
|
1027
|
+
return DecodeObject(call->instance, (const uint8_t *)rax, inst->type);
|
|
1027
1028
|
}
|
|
1028
1029
|
|
|
1029
1030
|
#undef INTEGER_SWAP
|
|
@@ -1043,14 +1044,14 @@ namespace {
|
|
|
1043
1044
|
HandleRunAggregateDD,
|
|
1044
1045
|
HandleRunAggregateGD,
|
|
1045
1046
|
HandleRunAggregateDG,
|
|
1046
|
-
|
|
1047
|
+
HandleRunAggregateMem,
|
|
1047
1048
|
#define PRIMITIVE(Name) HandleRun ## Name ## X,
|
|
1048
1049
|
#include "../primitives.inc"
|
|
1049
1050
|
HandleRunAggregateGGX,
|
|
1050
1051
|
HandleRunAggregateDDX,
|
|
1051
1052
|
HandleRunAggregateGDX,
|
|
1052
1053
|
HandleRunAggregateDGX,
|
|
1053
|
-
|
|
1054
|
+
HandleRunAggregateMemX,
|
|
1054
1055
|
HandleYield,
|
|
1055
1056
|
HandleCallGG,
|
|
1056
1057
|
HandleCallF,
|
|
@@ -1067,7 +1068,7 @@ namespace {
|
|
|
1067
1068
|
#define PRIMITIVE(Name) HandleReturn ## Name,
|
|
1068
1069
|
#include "../primitives.inc"
|
|
1069
1070
|
HandleReturnAggregateReg,
|
|
1070
|
-
|
|
1071
|
+
HandleReturnAggregateMem
|
|
1071
1072
|
};
|
|
1072
1073
|
|
|
1073
1074
|
FORCE_INLINE napi_value RunLoop(CallData *call, napi_value *args, uint8_t *base, const AbiInstruction *inst)
|
|
@@ -1232,9 +1233,9 @@ void CallData::Relay(Size idx, uint8_t *sp)
|
|
|
1232
1233
|
buf[0] = *(uint64_t *)(in_ptr + param.abi.offsets[0]);
|
|
1233
1234
|
buf[1] = *(uint64_t *)(in_ptr + param.abi.offsets[1]);
|
|
1234
1235
|
|
|
1235
|
-
arguments[i] = DecodeObject(
|
|
1236
|
+
arguments[i] = DecodeObject(instance, (const uint8_t *)buf, param.type);
|
|
1236
1237
|
} else {
|
|
1237
|
-
arguments[i] = DecodeObject(
|
|
1238
|
+
arguments[i] = DecodeObject(instance, in_ptr + param.abi.offsets[0], param.type);
|
|
1238
1239
|
}
|
|
1239
1240
|
} break;
|
|
1240
1241
|
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
#include "lib/native/base/base.hh"
|
|
7
7
|
#include "../ffi.hh"
|
|
8
8
|
#include "../call.hh"
|
|
9
|
+
#include "../type.hh"
|
|
9
10
|
#include "../util.hh"
|
|
10
11
|
#include "../win32.hh"
|
|
11
12
|
|
|
@@ -29,15 +30,15 @@ enum class AbiOpcode {
|
|
|
29
30
|
#define PRIMITIVE(Name) Push ## Name,
|
|
30
31
|
#include "../primitives.inc"
|
|
31
32
|
PushAggregateReg,
|
|
32
|
-
|
|
33
|
+
PushAggregateMem,
|
|
33
34
|
#define PRIMITIVE(Name) Run ## Name,
|
|
34
35
|
#include "../primitives.inc"
|
|
35
36
|
RunAggregateReg,
|
|
36
|
-
|
|
37
|
+
RunAggregateMem,
|
|
37
38
|
#define PRIMITIVE(Name) Run ## Name ## X,
|
|
38
39
|
#include "../primitives.inc"
|
|
39
40
|
RunAggregateRegX,
|
|
40
|
-
|
|
41
|
+
RunAggregateMemX,
|
|
41
42
|
Yield,
|
|
42
43
|
CallG,
|
|
43
44
|
CallF,
|
|
@@ -50,12 +51,12 @@ enum class AbiOpcode {
|
|
|
50
51
|
#define PRIMITIVE(Name) Return ## Name,
|
|
51
52
|
#include "../primitives.inc"
|
|
52
53
|
ReturnAggregateReg,
|
|
53
|
-
|
|
54
|
+
ReturnAggregateMem
|
|
54
55
|
};
|
|
55
56
|
|
|
56
57
|
namespace {
|
|
57
58
|
#if defined(MUST_TAIL)
|
|
58
|
-
PRESERVE_NONE typedef napi_value ForwardFunc(CallData *call, napi_value *args,
|
|
59
|
+
PRESERVE_NONE typedef napi_value ForwardFunc(CallData *call, napi_value *args, uint8_t *base, const AbiInstruction *inst);
|
|
59
60
|
|
|
60
61
|
extern ForwardFunc *const ForwardDispatch[256];
|
|
61
62
|
|
|
@@ -82,16 +83,16 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
|
|
|
82
83
|
param.regular = IsRegularSize(param.type->size, 8);
|
|
83
84
|
|
|
84
85
|
if (param.type->primitive == PrimitiveKind::Record || param.type->primitive == PrimitiveKind::Union) {
|
|
85
|
-
AbiOpcode code = param.regular ? AbiOpcode::PushAggregateReg : AbiOpcode::
|
|
86
|
+
AbiOpcode code = param.regular ? AbiOpcode::PushAggregateReg : AbiOpcode::PushAggregateMem;
|
|
86
87
|
|
|
87
|
-
func->sync.Append({ .op = Code2Op(code), .a = param.offset, .b1 = arg, .b2 = (int16_t)param.directions, .type = param.type });
|
|
88
|
-
func->async.Append({ .op = Code2Op(code), .a = param.offset, .b1 = arg, .b2 = (int16_t)param.directions, .type = param.type });
|
|
88
|
+
func->sync.Append({ .op = Code2Op(code), .a = param.offset, .b1 = (int16_t)(arg * 8), .b2 = (int16_t)param.directions, .type = param.type });
|
|
89
|
+
func->async.Append({ .op = Code2Op(code), .a = param.offset, .b1 = (int16_t)(arg * 8), .b2 = (int16_t)param.directions, .type = param.type });
|
|
89
90
|
} else {
|
|
90
91
|
int delta = (int)AbiOpcode::PushVoid - (int)PrimitiveKind::Void;
|
|
91
92
|
AbiOpcode code = (AbiOpcode)((int)param.type->primitive + delta);
|
|
92
93
|
|
|
93
|
-
func->sync.Append({ .op = Code2Op(code), .a = param.offset, .b1 = arg, .b2 = (int16_t)param.directions, .type = param.type });
|
|
94
|
-
func->async.Append({ .op = Code2Op(code), .a = param.offset, .b1 = arg, .b2 = (int16_t)param.directions, .type = param.type });
|
|
94
|
+
func->sync.Append({ .op = Code2Op(code), .a = param.offset, .b1 = (int16_t)(arg * 8), .b2 = (int16_t)param.directions, .type = param.type });
|
|
95
|
+
func->async.Append({ .op = Code2Op(code), .a = param.offset, .b1 = (int16_t)(arg * 8), .b2 = (int16_t)param.directions, .type = param.type });
|
|
95
96
|
}
|
|
96
97
|
|
|
97
98
|
func->forward_fp |= IsFloat(param.type);
|
|
@@ -175,12 +176,12 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
|
|
|
175
176
|
func->async.Append({ .op = Code2Op(call) });
|
|
176
177
|
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateReg), .type = func->ret.type });
|
|
177
178
|
} else {
|
|
178
|
-
AbiOpcode run = func->forward_fp ? AbiOpcode::
|
|
179
|
+
AbiOpcode run = func->forward_fp ? AbiOpcode::RunAggregateMemX : AbiOpcode::RunAggregateMem;
|
|
179
180
|
AbiOpcode call = func->forward_fp ? AbiOpcode::CallStackX : AbiOpcode::CallStack;
|
|
180
181
|
|
|
181
182
|
func->sync.Append({ .op = Code2Op(run), .a = (int32_t)func->ret.type->size, .type = func->ret.type });
|
|
182
183
|
func->async.Append({ .op = Code2Op(call), .a = (int32_t)func->ret.type->size });
|
|
183
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
184
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateMem), .type = func->ret.type });
|
|
184
185
|
}
|
|
185
186
|
} break;
|
|
186
187
|
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
@@ -216,7 +217,7 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
|
|
|
216
217
|
namespace {
|
|
217
218
|
#if defined(MUST_TAIL)
|
|
218
219
|
#define OP(Code) \
|
|
219
|
-
PRESERVE_NONE napi_value Handle ## Code(CallData *call, napi_value *args,
|
|
220
|
+
PRESERVE_NONE napi_value Handle ## Code(CallData *call, napi_value *args, uint8_t *base, const AbiInstruction *inst)
|
|
220
221
|
#define NEXT() \
|
|
221
222
|
do { \
|
|
222
223
|
const AbiInstruction *next = inst + 1; \
|
|
@@ -228,7 +229,7 @@ namespace {
|
|
|
228
229
|
#define NEXT() \
|
|
229
230
|
break
|
|
230
231
|
|
|
231
|
-
napi_value RunLoop(CallData *call, napi_value *args,
|
|
232
|
+
napi_value RunLoop(CallData *call, napi_value *args, uint8_t *base, const AbiInstruction *inst)
|
|
232
233
|
{
|
|
233
234
|
for (;; ++inst) {
|
|
234
235
|
switch ((intptr_t)inst->op) {
|
|
@@ -255,7 +256,7 @@ namespace {
|
|
|
255
256
|
return call->env.Null(); \
|
|
256
257
|
} \
|
|
257
258
|
\
|
|
258
|
-
*(base + inst->b1) = (uint64_t)v; \
|
|
259
|
+
*(uint64_t *)(base + inst->b1) = (uint64_t)v; \
|
|
259
260
|
} while (false)
|
|
260
261
|
#define INTEGER_SWAP(CType) \
|
|
261
262
|
do { \
|
|
@@ -265,7 +266,7 @@ namespace {
|
|
|
265
266
|
return call->env.Null(); \
|
|
266
267
|
} \
|
|
267
268
|
\
|
|
268
|
-
*(base + inst->b1) = (uint64_t)ReverseBytes(v); \
|
|
269
|
+
*(uint64_t *)(base + inst->b1) = (uint64_t)ReverseBytes(v); \
|
|
269
270
|
} while (false)
|
|
270
271
|
|
|
271
272
|
OP(PushVoid) { K_UNREACHABLE(); return call->env.Null(); }
|
|
@@ -381,7 +382,7 @@ namespace {
|
|
|
381
382
|
|
|
382
383
|
NEXT();
|
|
383
384
|
}
|
|
384
|
-
OP(
|
|
385
|
+
OP(PushAggregateMem) {
|
|
385
386
|
napi_value arg = args[inst->a];
|
|
386
387
|
|
|
387
388
|
if (!IsObject(call->env, arg)) [[unlikely]] {
|
|
@@ -403,12 +404,12 @@ namespace {
|
|
|
403
404
|
|
|
404
405
|
#define INTEGER(Suffix, CType) \
|
|
405
406
|
do { \
|
|
406
|
-
uint64_t rax = WRAP(ForwardCall ## Suffix(call->native,
|
|
407
|
+
uint64_t rax = WRAP(ForwardCall ## Suffix(call->native, base, &call->saved_sp)); \
|
|
407
408
|
return NewInt(call->env, (CType)rax); \
|
|
408
409
|
} while (false)
|
|
409
410
|
#define INTEGER_SWAP(Suffix, CType) \
|
|
410
411
|
do { \
|
|
411
|
-
uint64_t rax = WRAP(ForwardCall ## Suffix(call->native,
|
|
412
|
+
uint64_t rax = WRAP(ForwardCall ## Suffix(call->native, base, &call->saved_sp)); \
|
|
412
413
|
return NewInt(call->env, ReverseBytes((CType)rax)); \
|
|
413
414
|
} while (false)
|
|
414
415
|
#define DISPOSE(Ptr) \
|
|
@@ -419,11 +420,11 @@ namespace {
|
|
|
419
420
|
} while (false)
|
|
420
421
|
|
|
421
422
|
OP(RunVoid) {
|
|
422
|
-
WRAP(ForwardCallG(call->native,
|
|
423
|
+
WRAP(ForwardCallG(call->native, base, &call->saved_sp));
|
|
423
424
|
return nullptr;
|
|
424
425
|
}
|
|
425
426
|
OP(RunBool) {
|
|
426
|
-
uint64_t rax = WRAP(ForwardCallG(call->native,
|
|
427
|
+
uint64_t rax = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
|
|
427
428
|
return Napi::Boolean::New(call->env, rax & 0x1);
|
|
428
429
|
}
|
|
429
430
|
OP(RunInt8) { INTEGER(G, int8_t); }
|
|
@@ -441,60 +442,60 @@ namespace {
|
|
|
441
442
|
OP(RunUInt64) { INTEGER(G, uint64_t); }
|
|
442
443
|
OP(RunUInt64S) { INTEGER_SWAP(G, uint64_t); }
|
|
443
444
|
OP(RunString) {
|
|
444
|
-
uint64_t rax = WRAP(ForwardCallG(call->native,
|
|
445
|
+
uint64_t rax = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
|
|
445
446
|
napi_value value = rax ? Napi::String::New(call->env, (const char *)rax) : call->env.Null();
|
|
446
447
|
DISPOSE((void *)rax);
|
|
447
448
|
return value;
|
|
448
449
|
}
|
|
449
450
|
OP(RunString16) {
|
|
450
|
-
uint64_t rax = WRAP(ForwardCallG(call->native,
|
|
451
|
+
uint64_t rax = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
|
|
451
452
|
napi_value value = rax ? Napi::String::New(call->env, (const char16_t *)rax) : call->env.Null();
|
|
452
453
|
DISPOSE((void *)rax);
|
|
453
454
|
return value;
|
|
454
455
|
}
|
|
455
456
|
OP(RunString32) {
|
|
456
|
-
uint64_t rax = WRAP(ForwardCallG(call->native,
|
|
457
|
+
uint64_t rax = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
|
|
457
458
|
napi_value value = rax ? MakeStringFromUTF32(call->env, (const char32_t *)rax) : call->env.Null();
|
|
458
459
|
DISPOSE((void *)rax);
|
|
459
460
|
return value;
|
|
460
461
|
}
|
|
461
462
|
OP(RunPointer) {
|
|
462
|
-
uint64_t rax = WRAP(ForwardCallG(call->native,
|
|
463
|
+
uint64_t rax = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
|
|
463
464
|
napi_value value = rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
|
|
464
465
|
DISPOSE((void *)rax);
|
|
465
466
|
return value;
|
|
466
467
|
}
|
|
467
468
|
OP(RunCallback) {
|
|
468
|
-
uint64_t rax = WRAP(ForwardCallG(call->native,
|
|
469
|
+
uint64_t rax = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
|
|
469
470
|
return rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
|
|
470
471
|
}
|
|
471
472
|
OP(RunRecord) { K_UNREACHABLE(); return call->env.Null(); }
|
|
472
473
|
OP(RunUnion) { K_UNREACHABLE(); return call->env.Null(); }
|
|
473
474
|
OP(RunArray) { K_UNREACHABLE(); return call->env.Null(); }
|
|
474
475
|
OP(RunFloat32) {
|
|
475
|
-
float f = WRAP(ForwardCallF(call->native,
|
|
476
|
+
float f = WRAP(ForwardCallF(call->native, base, &call->saved_sp));
|
|
476
477
|
return Napi::Number::New(call->env, (double)f);
|
|
477
478
|
}
|
|
478
479
|
OP(RunFloat64) {
|
|
479
|
-
double d = WRAP(ForwardCallD(call->native,
|
|
480
|
+
double d = WRAP(ForwardCallD(call->native, base, &call->saved_sp));
|
|
480
481
|
return Napi::Number::New(call->env, d);
|
|
481
482
|
}
|
|
482
483
|
OP(RunPrototype) { K_UNREACHABLE(); return call->env.Null(); }
|
|
483
484
|
OP(RunAggregateReg) {
|
|
484
|
-
auto ret = WRAP(ForwardCallG(call->native,
|
|
485
|
-
return DecodeObject(call->
|
|
485
|
+
auto ret = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
|
|
486
|
+
return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
|
|
486
487
|
}
|
|
487
|
-
OP(
|
|
488
|
+
OP(RunAggregateMem) {
|
|
488
489
|
*(uint8_t **)base = call->AllocHeap(inst->a);
|
|
489
|
-
uint64_t rax = WRAP(ForwardCallG(call->native,
|
|
490
|
-
return DecodeObject(call->
|
|
490
|
+
uint64_t rax = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
|
|
491
|
+
return DecodeObject(call->instance, (const uint8_t *)rax, inst->type);
|
|
491
492
|
}
|
|
492
493
|
OP(RunVoidX) {
|
|
493
|
-
WRAP(ForwardCallGX(call->native,
|
|
494
|
+
WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
|
|
494
495
|
return nullptr;
|
|
495
496
|
}
|
|
496
497
|
OP(RunBoolX) {
|
|
497
|
-
uint64_t rax = WRAP(ForwardCallGX(call->native,
|
|
498
|
+
uint64_t rax = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
|
|
498
499
|
return Napi::Boolean::New(call->env, rax & 0x1);
|
|
499
500
|
}
|
|
500
501
|
OP(RunInt8X) { INTEGER(GX, int8_t); }
|
|
@@ -512,53 +513,53 @@ namespace {
|
|
|
512
513
|
OP(RunUInt64X) { INTEGER(GX, uint64_t); }
|
|
513
514
|
OP(RunUInt64SX) { INTEGER_SWAP(GX, uint64_t); }
|
|
514
515
|
OP(RunStringX) {
|
|
515
|
-
uint64_t rax = WRAP(ForwardCallGX(call->native,
|
|
516
|
+
uint64_t rax = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
|
|
516
517
|
napi_value value = rax ? Napi::String::New(call->env, (const char *)rax) : call->env.Null();
|
|
517
518
|
DISPOSE((void *)rax);
|
|
518
519
|
return value;
|
|
519
520
|
}
|
|
520
521
|
OP(RunString16X) {
|
|
521
|
-
uint64_t rax = WRAP(ForwardCallGX(call->native,
|
|
522
|
+
uint64_t rax = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
|
|
522
523
|
napi_value value = rax ? Napi::String::New(call->env, (const char16_t *)rax) : call->env.Null();
|
|
523
524
|
DISPOSE((void *)rax);
|
|
524
525
|
return value;
|
|
525
526
|
}
|
|
526
527
|
OP(RunString32X) {
|
|
527
|
-
uint64_t rax = WRAP(ForwardCallGX(call->native,
|
|
528
|
+
uint64_t rax = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
|
|
528
529
|
napi_value value = rax ? MakeStringFromUTF32(call->env, (const char32_t *)rax) : call->env.Null();
|
|
529
530
|
DISPOSE((void *)rax);
|
|
530
531
|
return value;
|
|
531
532
|
}
|
|
532
533
|
OP(RunPointerX) {
|
|
533
|
-
uint64_t rax = WRAP(ForwardCallGX(call->native,
|
|
534
|
+
uint64_t rax = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
|
|
534
535
|
napi_value value = rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
|
|
535
536
|
DISPOSE((void *)rax);
|
|
536
537
|
return value;
|
|
537
538
|
}
|
|
538
539
|
OP(RunCallbackX) {
|
|
539
|
-
uint64_t rax = WRAP(ForwardCallGX(call->native,
|
|
540
|
+
uint64_t rax = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
|
|
540
541
|
return rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
|
|
541
542
|
}
|
|
542
543
|
OP(RunRecordX) { K_UNREACHABLE(); return call->env.Null(); }
|
|
543
544
|
OP(RunUnionX) { K_UNREACHABLE(); return call->env.Null(); }
|
|
544
545
|
OP(RunArrayX) { K_UNREACHABLE(); return call->env.Null(); }
|
|
545
546
|
OP(RunFloat32X) {
|
|
546
|
-
float f = WRAP(ForwardCallFX(call->native,
|
|
547
|
+
float f = WRAP(ForwardCallFX(call->native, base, &call->saved_sp));
|
|
547
548
|
return Napi::Number::New(call->env, (double)f);
|
|
548
549
|
}
|
|
549
550
|
OP(RunFloat64X) {
|
|
550
|
-
double d = WRAP(ForwardCallDX(call->native,
|
|
551
|
+
double d = WRAP(ForwardCallDX(call->native, base, &call->saved_sp));
|
|
551
552
|
return Napi::Number::New(call->env, d);
|
|
552
553
|
}
|
|
553
554
|
OP(RunPrototypeX) { K_UNREACHABLE(); return call->env.Null(); }
|
|
554
555
|
OP(RunAggregateRegX) {
|
|
555
|
-
auto ret = WRAP(ForwardCallGX(call->native,
|
|
556
|
-
return DecodeObject(call->
|
|
556
|
+
auto ret = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
|
|
557
|
+
return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
|
|
557
558
|
}
|
|
558
|
-
OP(
|
|
559
|
+
OP(RunAggregateMemX) {
|
|
559
560
|
*(uint8_t **)base = call->AllocHeap(inst->a);
|
|
560
|
-
uint64_t rax = WRAP(ForwardCallGX(call->native,
|
|
561
|
-
return DecodeObject(call->
|
|
561
|
+
uint64_t rax = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
|
|
562
|
+
return DecodeObject(call->instance, (const uint8_t *)rax, inst->type);
|
|
562
563
|
}
|
|
563
564
|
|
|
564
565
|
#undef DISPOSE
|
|
@@ -567,7 +568,7 @@ namespace {
|
|
|
567
568
|
|
|
568
569
|
#define CALL(Suffix) \
|
|
569
570
|
do { \
|
|
570
|
-
auto ret = WRAP(ForwardCall ## Suffix(call->native,
|
|
571
|
+
auto ret = WRAP(ForwardCall ## Suffix(call->native, base, &call->saved_sp)); \
|
|
571
572
|
memcpy(base, &ret, K_SIZE(ret)); \
|
|
572
573
|
} while (false)
|
|
573
574
|
#define DISPOSE() \
|
|
@@ -598,7 +599,7 @@ namespace {
|
|
|
598
599
|
OP(CallD) { CALL(D); return nullptr; }
|
|
599
600
|
OP(CallStack) {
|
|
600
601
|
*(uint8_t **)base = call->AllocHeap(inst->a);
|
|
601
|
-
*(uint64_t *)base = WRAP(ForwardCallG(call->native,
|
|
602
|
+
*(uint64_t *)base = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
|
|
602
603
|
return nullptr;
|
|
603
604
|
}
|
|
604
605
|
OP(CallGX) { CALL(GX); return nullptr; }
|
|
@@ -606,7 +607,7 @@ namespace {
|
|
|
606
607
|
OP(CallDX) { CALL(DX); return nullptr; }
|
|
607
608
|
OP(CallStackX) {
|
|
608
609
|
*(uint8_t **)base = call->AllocHeap(inst->a);
|
|
609
|
-
*(uint64_t *)base = WRAP(ForwardCallGX(call->native,
|
|
610
|
+
*(uint64_t *)base = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
|
|
610
611
|
return nullptr;
|
|
611
612
|
}
|
|
612
613
|
|
|
@@ -669,10 +670,10 @@ namespace {
|
|
|
669
670
|
return Napi::Number::New(call->env, d);
|
|
670
671
|
}
|
|
671
672
|
OP(ReturnPrototype) { K_UNREACHABLE(); return call->env.Null(); }
|
|
672
|
-
OP(ReturnAggregateReg) { return DecodeObject(call->
|
|
673
|
-
OP(
|
|
673
|
+
OP(ReturnAggregateReg) { return DecodeObject(call->instance, base, inst->type); }
|
|
674
|
+
OP(ReturnAggregateMem) {
|
|
674
675
|
uint64_t rax = *(uint64_t *)base;
|
|
675
|
-
return DecodeObject(call->
|
|
676
|
+
return DecodeObject(call->instance, (const uint8_t *)rax, inst->type);
|
|
676
677
|
}
|
|
677
678
|
|
|
678
679
|
#undef INTEGER_SWAP
|
|
@@ -685,15 +686,15 @@ namespace {
|
|
|
685
686
|
#define PRIMITIVE(Name) HandlePush ## Name,
|
|
686
687
|
#include "../primitives.inc"
|
|
687
688
|
HandlePushAggregateReg,
|
|
688
|
-
|
|
689
|
+
HandlePushAggregateMem,
|
|
689
690
|
#define PRIMITIVE(Name) HandleRun ## Name,
|
|
690
691
|
#include "../primitives.inc"
|
|
691
692
|
HandleRunAggregateReg,
|
|
692
|
-
|
|
693
|
+
HandleRunAggregateMem,
|
|
693
694
|
#define PRIMITIVE(Name) HandleRun ## Name ## X,
|
|
694
695
|
#include "../primitives.inc"
|
|
695
696
|
HandleRunAggregateRegX,
|
|
696
|
-
|
|
697
|
+
HandleRunAggregateMemX,
|
|
697
698
|
HandleYield,
|
|
698
699
|
HandleCallG,
|
|
699
700
|
HandleCallF,
|
|
@@ -706,10 +707,10 @@ namespace {
|
|
|
706
707
|
#define PRIMITIVE(Name) HandleReturn ## Name,
|
|
707
708
|
#include "../primitives.inc"
|
|
708
709
|
HandleReturnAggregateReg,
|
|
709
|
-
|
|
710
|
+
HandleReturnAggregateMem
|
|
710
711
|
};
|
|
711
712
|
|
|
712
|
-
FORCE_INLINE napi_value RunLoop(CallData *call, napi_value *args,
|
|
713
|
+
FORCE_INLINE napi_value RunLoop(CallData *call, napi_value *args, uint8_t *base, const AbiInstruction *inst)
|
|
713
714
|
{
|
|
714
715
|
return ((ForwardFunc *)inst->op)(call, args, base, inst);
|
|
715
716
|
}
|
|
@@ -738,7 +739,7 @@ napi_value CallData::Run(const FunctionInfo *func, napi_value *args)
|
|
|
738
739
|
return env.Null();
|
|
739
740
|
|
|
740
741
|
const AbiInstruction *first = func->sync.ptr;
|
|
741
|
-
return RunLoop(this, args,
|
|
742
|
+
return RunLoop(this, args, base, first);
|
|
742
743
|
}
|
|
743
744
|
|
|
744
745
|
bool CallData::PrepareAsync(const FunctionInfo *func, napi_value *args)
|
|
@@ -749,19 +750,19 @@ bool CallData::PrepareAsync(const FunctionInfo *func, napi_value *args)
|
|
|
749
750
|
async_base = base;
|
|
750
751
|
|
|
751
752
|
const AbiInstruction *first = func->async.ptr;
|
|
752
|
-
return !RunLoop(this, args,
|
|
753
|
+
return !RunLoop(this, args, base, first); // Yield returns nullptr
|
|
753
754
|
}
|
|
754
755
|
|
|
755
756
|
void CallData::ExecuteAsync()
|
|
756
757
|
{
|
|
757
758
|
const AbiInstruction *next = async_ip++;
|
|
758
|
-
RunLoop(this, nullptr,
|
|
759
|
+
RunLoop(this, nullptr, async_base, next);
|
|
759
760
|
}
|
|
760
761
|
|
|
761
762
|
napi_value CallData::EndAsync()
|
|
762
763
|
{
|
|
763
764
|
const AbiInstruction *next = async_ip++;
|
|
764
|
-
return RunLoop(this, nullptr,
|
|
765
|
+
return RunLoop(this, nullptr, async_base, next);
|
|
765
766
|
}
|
|
766
767
|
|
|
767
768
|
void CallData::Relay(Size idx, uint8_t *sp)
|
|
@@ -944,7 +945,7 @@ void CallData::Relay(Size idx, uint8_t *sp)
|
|
|
944
945
|
}
|
|
945
946
|
stk_ptr += (j >= 4);
|
|
946
947
|
|
|
947
|
-
arguments[i] = DecodeObject(
|
|
948
|
+
arguments[i] = DecodeObject(instance, ptr, param.type);
|
|
948
949
|
} break;
|
|
949
950
|
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
950
951
|
case PrimitiveKind::Float32: {
|