koffi 2.15.1 → 2.16.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/koffi/darwin_arm64/koffi.node +0 -0
- package/build/koffi/darwin_x64/koffi.node +0 -0
- package/build/koffi/freebsd_arm64/koffi.node +0 -0
- package/build/koffi/freebsd_ia32/koffi.node +0 -0
- package/build/koffi/freebsd_x64/koffi.node +0 -0
- package/build/koffi/linux_arm64/koffi.node +0 -0
- package/build/koffi/linux_armhf/koffi.node +0 -0
- package/build/koffi/linux_ia32/koffi.node +0 -0
- package/build/koffi/linux_loong64/koffi.node +0 -0
- package/build/koffi/linux_riscv64d/koffi.node +0 -0
- package/build/koffi/linux_x64/koffi.node +0 -0
- package/build/koffi/musl_arm64/koffi.node +0 -0
- package/build/koffi/musl_x64/koffi.node +0 -0
- package/build/koffi/openbsd_ia32/koffi.node +0 -0
- package/build/koffi/openbsd_x64/koffi.node +0 -0
- package/build/koffi/win32_arm64/koffi.node +0 -0
- package/build/koffi/win32_ia32/koffi.node +0 -0
- package/build/koffi/win32_x64/koffi.node +0 -0
- package/index.d.ts +11 -9
- package/index.js +8 -8
- package/indirect.js +8 -8
- package/package.json +1 -1
- package/src/koffi/src/abi_arm32.cc +222 -219
- package/src/koffi/src/abi_arm32_asm.S +1 -29
- package/src/koffi/src/abi_arm64.cc +257 -235
- package/src/koffi/src/abi_arm64_asm.S +1 -32
- package/src/koffi/src/abi_arm64_asm.asm +1 -23
- package/src/koffi/src/abi_loong64_asm.S +1 -25
- package/src/koffi/src/abi_riscv64.cc +220 -217
- package/src/koffi/src/abi_riscv64_asm.S +1 -25
- package/src/koffi/src/abi_x64_sysv.cc +196 -192
- package/src/koffi/src/abi_x64_sysv_asm.S +1 -31
- package/src/koffi/src/abi_x64_win.cc +188 -172
- package/src/koffi/src/abi_x64_win_asm.S +1 -19
- package/src/koffi/src/abi_x64_win_asm.asm +1 -21
- package/src/koffi/src/abi_x86.cc +224 -189
- package/src/koffi/src/abi_x86_asm.S +6 -25
- package/src/koffi/src/abi_x86_asm.asm +9 -22
- package/src/koffi/src/call.cc +246 -428
- package/src/koffi/src/call.hh +9 -8
- package/src/koffi/src/ffi.cc +140 -87
- package/src/koffi/src/ffi.hh +12 -58
- package/src/koffi/src/primitives.inc +39 -0
- package/src/koffi/src/trampolines/armasm.inc +0 -32770
- package/src/koffi/src/trampolines/gnu.inc +0 -24578
- package/src/koffi/src/trampolines/masm32.inc +0 -32770
- package/src/koffi/src/trampolines/masm64.inc +0 -32770
- package/src/koffi/src/trampolines/prototypes.inc +16385 -16385
- package/src/koffi/src/util.cc +149 -107
- package/src/koffi/src/util.hh +76 -40
|
@@ -29,8 +29,6 @@ extern "C" napi_value CallSwitchStack(Napi::Function *func, size_t argc, napi_va
|
|
|
29
29
|
uint8_t *old_sp, Span<uint8_t> *new_stack,
|
|
30
30
|
napi_value (*call)(Napi::Function *func, size_t argc, napi_value *argv));
|
|
31
31
|
|
|
32
|
-
#include "trampolines/prototypes.inc"
|
|
33
|
-
|
|
34
32
|
bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
|
|
35
33
|
{
|
|
36
34
|
func->ret.regular = IsRegularSize(func->ret.type->size, 8);
|
|
@@ -47,154 +45,212 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
|
|
|
47
45
|
|
|
48
46
|
bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
49
47
|
{
|
|
50
|
-
uint64_t *args_ptr =
|
|
48
|
+
uint64_t *args_ptr = AllocStack<uint64_t>(func->args_size);
|
|
51
49
|
|
|
52
|
-
|
|
53
|
-
if (!AllocStack(func->args_size, 16, &args_ptr)) [[unlikely]]
|
|
50
|
+
if (!args_ptr) [[unlikely]]
|
|
54
51
|
return false;
|
|
55
52
|
if (!func->ret.regular) {
|
|
56
53
|
return_ptr = AllocHeap(func->ret.type->size, 16);
|
|
57
54
|
*(uint8_t **)(args_ptr++) = return_ptr;
|
|
58
55
|
}
|
|
59
56
|
|
|
57
|
+
Size i = -1;
|
|
58
|
+
|
|
59
|
+
#if defined(__GNUC__) || defined(__clang__)
|
|
60
|
+
static const void *const DispatchTable[] = {
|
|
61
|
+
#define PRIMITIVE(Name) && Name,
|
|
62
|
+
#include "primitives.inc"
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
#define LOOP
|
|
66
|
+
#define CASE(Primitive) \
|
|
67
|
+
do { \
|
|
68
|
+
PrimitiveKind next = func->primitives[++i]; \
|
|
69
|
+
goto *DispatchTable[(int)next]; \
|
|
70
|
+
} while (false); \
|
|
71
|
+
Primitive:
|
|
72
|
+
#define OR(Primitive) \
|
|
73
|
+
Primitive:
|
|
74
|
+
#else
|
|
75
|
+
#define LOOP \
|
|
76
|
+
while (++i < func->parameters.len) \
|
|
77
|
+
switch (func->primitives[i])
|
|
78
|
+
#define CASE(Primitive) \
|
|
79
|
+
break; \
|
|
80
|
+
case PrimitiveKind::Primitive:
|
|
81
|
+
#define OR(Primitive) \
|
|
82
|
+
case PrimitiveKind::Primitive:
|
|
83
|
+
#endif
|
|
84
|
+
|
|
60
85
|
#define PUSH_INTEGER(CType) \
|
|
61
86
|
do { \
|
|
62
|
-
|
|
87
|
+
const ParameterInfo ¶m = func->parameters[i]; \
|
|
88
|
+
Napi::Value value = info[param.offset]; \
|
|
89
|
+
\
|
|
90
|
+
CType v; \
|
|
91
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
63
92
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
64
93
|
return false; \
|
|
65
94
|
} \
|
|
66
95
|
\
|
|
67
|
-
CType v = GetNumber<CType>(value); \
|
|
68
96
|
*(args_ptr++) = (uint64_t)v; \
|
|
69
97
|
} while (false)
|
|
70
98
|
#define PUSH_INTEGER_SWAP(CType) \
|
|
71
99
|
do { \
|
|
72
|
-
|
|
100
|
+
const ParameterInfo ¶m = func->parameters[i]; \
|
|
101
|
+
Napi::Value value = info[param.offset]; \
|
|
102
|
+
\
|
|
103
|
+
CType v; \
|
|
104
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
73
105
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
74
106
|
return false; \
|
|
75
107
|
} \
|
|
76
108
|
\
|
|
77
|
-
CType v = GetNumber<CType>(value); \
|
|
78
109
|
*(args_ptr++) = (uint64_t)ReverseBytes(v); \
|
|
79
110
|
} while (false)
|
|
80
111
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const ParameterInfo ¶m = func->parameters[i];
|
|
84
|
-
K_ASSERT(param.directions >= 1 && param.directions <= 3);
|
|
112
|
+
LOOP {
|
|
113
|
+
CASE(Void) { K_UNREACHABLE(); };
|
|
85
114
|
|
|
86
|
-
|
|
115
|
+
CASE(Bool) {
|
|
116
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
117
|
+
Napi::Value value = info[param.offset];
|
|
87
118
|
|
|
88
|
-
|
|
89
|
-
|
|
119
|
+
bool b;
|
|
120
|
+
if (napi_get_value_bool(env, value, &b) != napi_ok) [[unlikely]] {
|
|
121
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
90
124
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
125
|
+
*(bool *)(args_ptr++) = b;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
CASE(Int8) { PUSH_INTEGER(int8_t); };
|
|
129
|
+
CASE(UInt8) { PUSH_INTEGER(uint8_t); };
|
|
130
|
+
CASE(Int16) { PUSH_INTEGER(int16_t); };
|
|
131
|
+
CASE(Int16S) { PUSH_INTEGER_SWAP(int16_t); };
|
|
132
|
+
CASE(UInt16) { PUSH_INTEGER(uint16_t); };
|
|
133
|
+
CASE(UInt16S) { PUSH_INTEGER_SWAP(uint16_t); };
|
|
134
|
+
CASE(Int32) { PUSH_INTEGER(int32_t); };
|
|
135
|
+
CASE(Int32S) { PUSH_INTEGER_SWAP(int32_t); };
|
|
136
|
+
CASE(UInt32) { PUSH_INTEGER(uint32_t); };
|
|
137
|
+
CASE(UInt32S) { PUSH_INTEGER_SWAP(uint32_t); };
|
|
138
|
+
CASE(Int64) { PUSH_INTEGER(int64_t); };
|
|
139
|
+
CASE(Int64S) { PUSH_INTEGER_SWAP(int64_t); };
|
|
140
|
+
CASE(UInt64) { PUSH_INTEGER(uint64_t); };
|
|
141
|
+
CASE(UInt64S) { PUSH_INTEGER_SWAP(uint64_t); };
|
|
142
|
+
|
|
143
|
+
CASE(String) {
|
|
144
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
145
|
+
Napi::Value value = info[param.offset];
|
|
96
146
|
|
|
97
|
-
|
|
147
|
+
const char *str;
|
|
148
|
+
if (!PushString(value, param.directions, &str)) [[unlikely]]
|
|
149
|
+
return false;
|
|
98
150
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
case PrimitiveKind::Int16S: { PUSH_INTEGER_SWAP(int16_t); } break;
|
|
105
|
-
case PrimitiveKind::UInt16: { PUSH_INTEGER(uint16_t); } break;
|
|
106
|
-
case PrimitiveKind::UInt16S: { PUSH_INTEGER_SWAP(uint16_t); } break;
|
|
107
|
-
case PrimitiveKind::Int32: { PUSH_INTEGER(int32_t); } break;
|
|
108
|
-
case PrimitiveKind::Int32S: { PUSH_INTEGER_SWAP(int32_t); } break;
|
|
109
|
-
case PrimitiveKind::UInt32: { PUSH_INTEGER(uint32_t); } break;
|
|
110
|
-
case PrimitiveKind::UInt32S: { PUSH_INTEGER_SWAP(uint32_t); } break;
|
|
111
|
-
case PrimitiveKind::Int64: { PUSH_INTEGER(int64_t); } break;
|
|
112
|
-
case PrimitiveKind::Int64S: { PUSH_INTEGER_SWAP(int64_t); } break;
|
|
113
|
-
case PrimitiveKind::UInt64: { PUSH_INTEGER(uint64_t); } break;
|
|
114
|
-
case PrimitiveKind::UInt64S: { PUSH_INTEGER_SWAP(uint64_t); } break;
|
|
115
|
-
case PrimitiveKind::String: {
|
|
116
|
-
const char *str;
|
|
117
|
-
if (!PushString(value, param.directions, &str)) [[unlikely]]
|
|
118
|
-
return false;
|
|
151
|
+
*(const char **)(args_ptr++) = str;
|
|
152
|
+
};
|
|
153
|
+
CASE(String16) {
|
|
154
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
155
|
+
Napi::Value value = info[param.offset];
|
|
119
156
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const char16_t *str16;
|
|
124
|
-
if (!PushString16(value, param.directions, &str16)) [[unlikely]]
|
|
125
|
-
return false;
|
|
157
|
+
const char16_t *str16;
|
|
158
|
+
if (!PushString16(value, param.directions, &str16)) [[unlikely]]
|
|
159
|
+
return false;
|
|
126
160
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
return false;
|
|
161
|
+
*(const char16_t **)(args_ptr++) = str16;
|
|
162
|
+
};
|
|
163
|
+
CASE(String32) {
|
|
164
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
165
|
+
Napi::Value value = info[param.offset];
|
|
133
166
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
void *ptr;
|
|
138
|
-
if (!PushPointer(value, param.type, param.directions, &ptr)) [[unlikely]]
|
|
139
|
-
return false;
|
|
167
|
+
const char32_t *str32;
|
|
168
|
+
if (!PushString32(value, param.directions, &str32)) [[unlikely]]
|
|
169
|
+
return false;
|
|
140
170
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
case PrimitiveKind::Record:
|
|
144
|
-
case PrimitiveKind::Union: {
|
|
145
|
-
if (!IsObject(value)) [[unlikely]] {
|
|
146
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
|
|
147
|
-
return false;
|
|
148
|
-
}
|
|
171
|
+
*(const char32_t **)(args_ptr++) = str32;
|
|
172
|
+
};
|
|
149
173
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
} else {
|
|
154
|
-
ptr = AllocHeap(param.type->size, 16);
|
|
155
|
-
*(uint8_t **)(args_ptr++) = ptr;
|
|
156
|
-
}
|
|
174
|
+
CASE(Pointer) {
|
|
175
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
176
|
+
Napi::Value value = info[param.offset];
|
|
157
177
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
} break;
|
|
162
|
-
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
163
|
-
case PrimitiveKind::Float32: {
|
|
164
|
-
if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
|
|
165
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
166
|
-
return false;
|
|
167
|
-
}
|
|
178
|
+
void *ptr;
|
|
179
|
+
if (!PushPointer(value, param.type, param.directions, &ptr)) [[unlikely]]
|
|
180
|
+
return false;
|
|
168
181
|
|
|
169
|
-
|
|
182
|
+
*(void **)(args_ptr++) = ptr;
|
|
183
|
+
};
|
|
170
184
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
case PrimitiveKind::Float64: {
|
|
175
|
-
if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
|
|
176
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
177
|
-
return false;
|
|
178
|
-
}
|
|
185
|
+
CASE(Record) OR(Union) {
|
|
186
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
187
|
+
Napi::Value value = info[param.offset];
|
|
179
188
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
void *ptr;
|
|
185
|
-
if (!PushCallback(value, param.type, &ptr)) [[unlikely]]
|
|
186
|
-
return false;
|
|
189
|
+
if (!IsObject(value)) [[unlikely]] {
|
|
190
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
187
193
|
|
|
188
|
-
|
|
189
|
-
|
|
194
|
+
uint8_t *ptr;
|
|
195
|
+
if (param.regular) {
|
|
196
|
+
ptr = (uint8_t *)(args_ptr++);
|
|
197
|
+
} else {
|
|
198
|
+
ptr = AllocHeap(param.type->size, 16);
|
|
199
|
+
*(uint8_t **)(args_ptr++) = ptr;
|
|
200
|
+
}
|
|
190
201
|
|
|
191
|
-
|
|
192
|
-
|
|
202
|
+
Napi::Object obj = value.As<Napi::Object>();
|
|
203
|
+
if (!PushObject(obj, param.type, ptr))
|
|
204
|
+
return false;
|
|
205
|
+
};
|
|
206
|
+
CASE(Array) { K_UNREACHABLE(); };
|
|
207
|
+
|
|
208
|
+
CASE(Float32) {
|
|
209
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
210
|
+
Napi::Value value = info[param.offset];
|
|
211
|
+
|
|
212
|
+
float f;
|
|
213
|
+
if (!TryNumber(value, &f)) [[unlikely]] {
|
|
214
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
memset((uint8_t *)args_ptr + 4, 0, 4);
|
|
219
|
+
*(float *)(args_ptr++) = f;
|
|
220
|
+
};
|
|
221
|
+
CASE(Float64) {
|
|
222
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
223
|
+
Napi::Value value = info[param.offset];
|
|
224
|
+
|
|
225
|
+
double d;
|
|
226
|
+
if (!TryNumber(value, &d)) [[unlikely]] {
|
|
227
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
*(double *)(args_ptr++) = d;
|
|
232
|
+
};
|
|
233
|
+
CASE(Callback) {
|
|
234
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
235
|
+
Napi::Value value = info[param.offset];
|
|
236
|
+
|
|
237
|
+
void *ptr;
|
|
238
|
+
if (!PushCallback(value, param.type, &ptr)) [[unlikely]]
|
|
239
|
+
return false;
|
|
240
|
+
|
|
241
|
+
*(void **)(args_ptr++) = ptr;
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
CASE(Prototype) { /* End loop */ };
|
|
193
245
|
}
|
|
194
246
|
|
|
195
247
|
#undef PUSH_INTEGER_SWAP
|
|
196
248
|
#undef PUSH_INTEGER
|
|
197
249
|
|
|
250
|
+
#undef OR
|
|
251
|
+
#undef CASE
|
|
252
|
+
#undef LOOP
|
|
253
|
+
|
|
198
254
|
new_sp = mem->stack.end();
|
|
199
255
|
|
|
200
256
|
return true;
|
|
@@ -302,17 +358,8 @@ Napi::Value CallData::Complete(const FunctionInfo *func)
|
|
|
302
358
|
case PrimitiveKind::String: return result.ptr ? Napi::String::New(env, (const char *)result.ptr) : env.Null();
|
|
303
359
|
case PrimitiveKind::String16: return result.ptr ? Napi::String::New(env, (const char16_t *)result.ptr) : env.Null();
|
|
304
360
|
case PrimitiveKind::String32: return result.ptr ? MakeStringFromUTF32(env, (const char32_t *)result.ptr) : env.Null();
|
|
305
|
-
case PrimitiveKind::Pointer:
|
|
306
|
-
case PrimitiveKind::Callback:
|
|
307
|
-
if (result.ptr) {
|
|
308
|
-
Napi::External<void> external = Napi::External<void>::New(env, result.ptr);
|
|
309
|
-
SetValueTag(external, func->ret.type->ref.marker);
|
|
310
|
-
|
|
311
|
-
return external;
|
|
312
|
-
} else {
|
|
313
|
-
return env.Null();
|
|
314
|
-
}
|
|
315
|
-
} break;
|
|
361
|
+
case PrimitiveKind::Pointer: return result.ptr ? WrapPointer(env, func->ret.type->ref.type, result.ptr) : env.Null();
|
|
362
|
+
case PrimitiveKind::Callback: return result.ptr ? WrapCallback(env, func->ret.type->ref.type, result.ptr) : env.Null();
|
|
316
363
|
case PrimitiveKind::Record:
|
|
317
364
|
case PrimitiveKind::Union: {
|
|
318
365
|
const uint8_t *ptr = return_ptr ? (const uint8_t *)return_ptr
|
|
@@ -520,19 +567,23 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
520
567
|
Napi::Value arg = str32 ? MakeStringFromUTF32(env, str32) : env.Null();
|
|
521
568
|
arguments.Append(arg);
|
|
522
569
|
} break;
|
|
523
|
-
case PrimitiveKind::Pointer:
|
|
524
|
-
case PrimitiveKind::Callback: {
|
|
570
|
+
case PrimitiveKind::Pointer: {
|
|
525
571
|
void *ptr2 = *(void **)(j < 4 ? gpr_ptr + j : args_ptr);
|
|
526
572
|
args_ptr += (j >= 4);
|
|
527
573
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
SetValueTag(external, param.type->ref.marker);
|
|
574
|
+
Napi::Value p = ptr2 ? WrapPointer(env, param.type->ref.type, ptr2) : env.Null();
|
|
575
|
+
arguments.Append(p);
|
|
531
576
|
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
arguments.Append(env.Null());
|
|
577
|
+
if (param.type->dispose) {
|
|
578
|
+
param.type->dispose(env, param.type, ptr2);
|
|
535
579
|
}
|
|
580
|
+
} break;
|
|
581
|
+
case PrimitiveKind::Callback: {
|
|
582
|
+
void *ptr2 = *(void **)(j < 4 ? gpr_ptr + j : args_ptr);
|
|
583
|
+
args_ptr += (j >= 4);
|
|
584
|
+
|
|
585
|
+
Napi::Value p = ptr2 ? WrapCallback(env, param.type->ref.type, ptr2) : env.Null();
|
|
586
|
+
arguments.Append(p);
|
|
536
587
|
|
|
537
588
|
if (param.type->dispose) {
|
|
538
589
|
param.type->dispose(env, param.type, ptr2);
|
|
@@ -588,34 +639,34 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
588
639
|
|
|
589
640
|
#define RETURN_INTEGER(CType) \
|
|
590
641
|
do { \
|
|
591
|
-
|
|
642
|
+
CType v; \
|
|
643
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
592
644
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
593
645
|
return; \
|
|
594
646
|
} \
|
|
595
647
|
\
|
|
596
|
-
CType v = GetNumber<CType>(value); \
|
|
597
648
|
out_reg->rax = (uint64_t)v; \
|
|
598
649
|
} while (false)
|
|
599
650
|
#define RETURN_INTEGER_SWAP(CType) \
|
|
600
651
|
do { \
|
|
601
|
-
|
|
652
|
+
CType v; \
|
|
653
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
602
654
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
603
655
|
return; \
|
|
604
656
|
} \
|
|
605
657
|
\
|
|
606
|
-
CType v = GetNumber<CType>(value); \
|
|
607
658
|
out_reg->rax = (uint64_t)ReverseBytes(v); \
|
|
608
659
|
} while (false)
|
|
609
660
|
|
|
610
661
|
switch (type->primitive) {
|
|
611
662
|
case PrimitiveKind::Void: {} break;
|
|
612
663
|
case PrimitiveKind::Bool: {
|
|
613
|
-
|
|
664
|
+
bool b;
|
|
665
|
+
if (napi_get_value_bool(env, value, &b) != napi_ok) [[unlikely]] {
|
|
614
666
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
|
|
615
667
|
return;
|
|
616
668
|
}
|
|
617
669
|
|
|
618
|
-
bool b = value.As<Napi::Boolean>();
|
|
619
670
|
out_reg->rax = (uint64_t)b;
|
|
620
671
|
} break;
|
|
621
672
|
case PrimitiveKind::Int8: { RETURN_INTEGER(int8_t); } break;
|
|
@@ -654,24 +705,9 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
654
705
|
out_reg->rax = (uint64_t)str32;
|
|
655
706
|
} break;
|
|
656
707
|
case PrimitiveKind::Pointer: {
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
if (CheckValueTag(value, type->ref.marker)) {
|
|
660
|
-
ptr = value.As<Napi::External<uint8_t>>().Data();
|
|
661
|
-
} else if (IsObject(value) && (type->ref.type->primitive == PrimitiveKind::Record ||
|
|
662
|
-
type->ref.type->primitive == PrimitiveKind::Union)) {
|
|
663
|
-
Napi::Object obj = value.As<Napi::Object>();
|
|
664
|
-
|
|
665
|
-
ptr = AllocHeap(type->ref.type->size, 16);
|
|
666
|
-
|
|
667
|
-
if (!PushObject(obj, type->ref.type, ptr))
|
|
668
|
-
return;
|
|
669
|
-
} else if (IsNullOrUndefined(value)) {
|
|
670
|
-
ptr = nullptr;
|
|
671
|
-
} else {
|
|
672
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
|
|
708
|
+
void *ptr;
|
|
709
|
+
if (!PushPointer(value, type, 1, &ptr)) [[unlikely]]
|
|
673
710
|
return;
|
|
674
|
-
}
|
|
675
711
|
|
|
676
712
|
out_reg->rax = (uint64_t)ptr;
|
|
677
713
|
} break;
|
|
@@ -694,42 +730,28 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
694
730
|
} break;
|
|
695
731
|
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
696
732
|
case PrimitiveKind::Float32: {
|
|
697
|
-
|
|
733
|
+
float f;
|
|
734
|
+
if (!TryNumber(value, &f)) [[unlikely]] {
|
|
698
735
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
699
736
|
return;
|
|
700
737
|
}
|
|
701
738
|
|
|
702
|
-
float f = GetNumber<float>(value);
|
|
703
|
-
|
|
704
739
|
memset((uint8_t *)&out_reg->xmm0 + 4, 0, 4);
|
|
705
740
|
memcpy(&out_reg->xmm0, &f, 4);
|
|
706
741
|
} break;
|
|
707
742
|
case PrimitiveKind::Float64: {
|
|
708
|
-
|
|
743
|
+
double d;
|
|
744
|
+
if (!TryNumber(value, &d)) [[unlikely]] {
|
|
709
745
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
710
746
|
return;
|
|
711
747
|
}
|
|
712
748
|
|
|
713
|
-
double d = GetNumber<double>(value);
|
|
714
749
|
out_reg->xmm0 = d;
|
|
715
750
|
} break;
|
|
716
751
|
case PrimitiveKind::Callback: {
|
|
717
752
|
void *ptr;
|
|
718
|
-
|
|
719
|
-
if (value.IsFunction()) {
|
|
720
|
-
Napi::Function func2 = value.As<Napi::Function>();
|
|
721
|
-
|
|
722
|
-
ptr = ReserveTrampoline(type->ref.proto, func2);
|
|
723
|
-
if (!ptr) [[unlikely]]
|
|
724
|
-
return;
|
|
725
|
-
} else if (CheckValueTag(value, type->ref.marker)) {
|
|
726
|
-
ptr = value.As<Napi::External<void>>().Data();
|
|
727
|
-
} else if (IsNullOrUndefined(value)) {
|
|
728
|
-
ptr = nullptr;
|
|
729
|
-
} else {
|
|
730
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
|
|
753
|
+
if (!PushCallback(value, type, &ptr)) [[unlikely]]
|
|
731
754
|
return;
|
|
732
|
-
}
|
|
733
755
|
|
|
734
756
|
out_reg->rax = (uint64_t)ptr;
|
|
735
757
|
} break;
|
|
@@ -743,12 +765,6 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
743
765
|
err_guard.Disable();
|
|
744
766
|
}
|
|
745
767
|
|
|
746
|
-
void *GetTrampoline(int16_t idx, const FunctionInfo *proto)
|
|
747
|
-
{
|
|
748
|
-
bool xmm = proto->forward_fp || IsFloat(proto->ret.type);
|
|
749
|
-
return Trampolines[idx][xmm];
|
|
750
|
-
}
|
|
751
|
-
|
|
752
768
|
}
|
|
753
769
|
|
|
754
770
|
#endif
|
|
@@ -90,30 +90,12 @@ ForwardCallXD:
|
|
|
90
90
|
.global RelayCallback
|
|
91
91
|
.global CallSwitchStack
|
|
92
92
|
|
|
93
|
-
# First, make a copy of
|
|
93
|
+
# First, make a copy of argument registers.
|
|
94
94
|
# Then call the C function RelayCallback with the following arguments:
|
|
95
95
|
# static trampoline ID, a pointer to the saved GPR array, a pointer to the stack
|
|
96
96
|
# arguments of this call, and a pointer to a struct that will contain the result registers.
|
|
97
97
|
# After the call, simply load these registers from the output struct.
|
|
98
98
|
.macro trampoline id
|
|
99
|
-
endbr64
|
|
100
|
-
subq $120, %rsp
|
|
101
|
-
movq %rcx, 32(%rsp)
|
|
102
|
-
movq %rdx, 40(%rsp)
|
|
103
|
-
movq %r8, 48(%rsp)
|
|
104
|
-
movq %r9, 56(%rsp)
|
|
105
|
-
movq $\id, %rcx
|
|
106
|
-
leaq 32(%rsp), %rdx
|
|
107
|
-
leaq 160(%rsp), %r8
|
|
108
|
-
leaq 96(%rsp), %r9
|
|
109
|
-
call RelayCallback
|
|
110
|
-
movq 96(%rsp), %rax
|
|
111
|
-
addq $120, %rsp
|
|
112
|
-
ret
|
|
113
|
-
.endm
|
|
114
|
-
|
|
115
|
-
# Same thing, but also forward the XMM argument registers and load the XMM result registers.
|
|
116
|
-
.macro trampoline_vec id
|
|
117
99
|
endbr64
|
|
118
100
|
subq $120, %rsp
|
|
119
101
|
movq %rcx, 32(%rsp)
|
|
@@ -103,32 +103,12 @@ ForwardCallXD endp
|
|
|
103
103
|
extern RelayCallback : PROC
|
|
104
104
|
public CallSwitchStack
|
|
105
105
|
|
|
106
|
-
; First, make a copy of
|
|
106
|
+
; First, make a copy of argument registers.
|
|
107
107
|
; Then call the C function RelayCallback with the following arguments:
|
|
108
108
|
; static trampoline ID, a pointer to the saved GPR array, a pointer to the stack
|
|
109
109
|
; arguments of this call, and a pointer to a struct that will contain the result registers.
|
|
110
110
|
; After the call, simply load these registers from the output struct.
|
|
111
111
|
trampoline macro ID
|
|
112
|
-
endbr64
|
|
113
|
-
sub rsp, 120
|
|
114
|
-
.allocstack 120
|
|
115
|
-
.endprolog
|
|
116
|
-
mov qword ptr [rsp+32], rcx
|
|
117
|
-
mov qword ptr [rsp+40], rdx
|
|
118
|
-
mov qword ptr [rsp+48], r8
|
|
119
|
-
mov qword ptr [rsp+56], r9
|
|
120
|
-
mov rcx, ID
|
|
121
|
-
lea rdx, qword ptr [rsp+32]
|
|
122
|
-
lea r8, qword ptr [rsp+160]
|
|
123
|
-
lea r9, qword ptr [rsp+96]
|
|
124
|
-
call RelayCallback
|
|
125
|
-
mov rax, qword ptr [rsp+96]
|
|
126
|
-
add rsp, 120
|
|
127
|
-
ret
|
|
128
|
-
endm
|
|
129
|
-
|
|
130
|
-
; Same thing, but also forward the XMM argument registers and load the XMM result registers.
|
|
131
|
-
trampoline_vec macro ID
|
|
132
112
|
endbr64
|
|
133
113
|
sub rsp, 120
|
|
134
114
|
.allocstack 120
|