koffi 1.0.5 → 1.1.0-beta.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.
Files changed (39) hide show
  1. package/CMakeLists.txt +4 -0
  2. package/README.md +54 -24
  3. package/build/qemu/1.1.0-beta.2/koffi_darwin_x64.tar.gz +0 -0
  4. package/build/qemu/1.1.0-beta.2/koffi_freebsd_arm64.tar.gz +0 -0
  5. package/build/qemu/1.1.0-beta.2/koffi_freebsd_ia32.tar.gz +0 -0
  6. package/build/qemu/1.1.0-beta.2/koffi_freebsd_x64.tar.gz +0 -0
  7. package/build/qemu/1.1.0-beta.2/koffi_linux_arm.tar.gz +0 -0
  8. package/build/qemu/1.1.0-beta.2/koffi_linux_arm64.tar.gz +0 -0
  9. package/build/qemu/1.1.0-beta.2/koffi_linux_ia32.tar.gz +0 -0
  10. package/build/qemu/1.1.0-beta.2/koffi_linux_x64.tar.gz +0 -0
  11. package/build/qemu/1.1.0-beta.2/koffi_win32_ia32.tar.gz +0 -0
  12. package/build/qemu/1.1.0-beta.2/koffi_win32_x64.tar.gz +0 -0
  13. package/package.json +1 -1
  14. package/qemu/qemu.js +12 -5
  15. package/qemu/registry/machines.json +20 -10
  16. package/src/abi_arm32.cc +40 -51
  17. package/src/abi_arm64.cc +71 -138
  18. package/src/abi_x64_sysv.cc +37 -13
  19. package/src/abi_x64_win.cc +16 -6
  20. package/src/abi_x86.cc +16 -6
  21. package/src/call.cc +564 -58
  22. package/src/call.hh +32 -44
  23. package/src/ffi.cc +218 -19
  24. package/src/ffi.hh +27 -11
  25. package/src/parser.cc +4 -0
  26. package/src/util.cc +72 -0
  27. package/src/util.hh +2 -0
  28. package/test/misc.c +16 -10
  29. package/build/qemu/1.0.5/koffi_darwin_x64.tar.gz +0 -0
  30. package/build/qemu/1.0.5/koffi_freebsd_arm64.tar.gz +0 -0
  31. package/build/qemu/1.0.5/koffi_freebsd_ia32.tar.gz +0 -0
  32. package/build/qemu/1.0.5/koffi_freebsd_x64.tar.gz +0 -0
  33. package/build/qemu/1.0.5/koffi_linux_arm.tar.gz +0 -0
  34. package/build/qemu/1.0.5/koffi_linux_arm64.tar.gz +0 -0
  35. package/build/qemu/1.0.5/koffi_linux_ia32.tar.gz +0 -0
  36. package/build/qemu/1.0.5/koffi_linux_x64.tar.gz +0 -0
  37. package/build/qemu/1.0.5/koffi_win32_ia32.tar.gz +0 -0
  38. package/build/qemu/1.0.5/koffi_win32_x64.tar.gz +0 -0
  39. package/test/misc.js +0 -227
package/src/abi_arm64.cc CHANGED
@@ -41,28 +41,9 @@ extern "C" X0X1Ret ForwardCallXGG(const void *func, uint8_t *sp);
41
41
  extern "C" float ForwardCallXF(const void *func, uint8_t *sp);
42
42
  extern "C" HfaRet ForwardCallXDDDD(const void *func, uint8_t *sp);
43
43
 
44
- static bool IsHFA(const TypeInfo *type)
45
- {
46
- if (type->primitive != PrimitiveKind::Record)
47
- return false;
48
-
49
- if (type->members.len < 1 || type->members.len > 4)
50
- return false;
51
- if (type->members[0].type->primitive != PrimitiveKind::Float32 &&
52
- type->members[0].type->primitive != PrimitiveKind::Float64)
53
- return false;
54
-
55
- for (Size i = 1; i < type->members.len; i++) {
56
- if (type->members[i].type != type->members[0].type)
57
- return false;
58
- }
59
-
60
- return true;
61
- }
62
-
63
44
  bool AnalyseFunction(InstanceData *, FunctionInfo *func)
64
45
  {
65
- if (IsHFA(func->ret.type)) {
46
+ if (IsHFA(func->ret.type, 1, 4)) {
66
47
  func->ret.vec_count = func->ret.type->members.len;
67
48
  } else if (func->ret.type->size <= 16) {
68
49
  func->ret.gpr_count = (func->ret.type->size + 7) / 8;
@@ -99,20 +80,6 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
99
80
  gpr_avail--;
100
81
  }
101
82
  } break;
102
-
103
- case PrimitiveKind::Float32:
104
- case PrimitiveKind::Float64: {
105
- #ifdef __APPLE__
106
- if (param.variadic)
107
- break;
108
- #endif
109
-
110
- if (vec_avail) {
111
- param.vec_count = 1;
112
- vec_avail--;
113
- }
114
- } break;
115
-
116
83
  case PrimitiveKind::Record: {
117
84
  #ifdef __APPLE__
118
85
  if (param.variadic) {
@@ -121,7 +88,7 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
121
88
  }
122
89
  #endif
123
90
 
124
- if (IsHFA(param.type)) {
91
+ if (IsHFA(param.type, 1, 4)) {
125
92
  int vec_count = (int)param.type->members.len;
126
93
 
127
94
  if (vec_count <= vec_avail) {
@@ -148,6 +115,19 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
148
115
  param.use_memory = true;
149
116
  }
150
117
  } break;
118
+ case PrimitiveKind::Array: { RG_UNREACHABLE(); } break;
119
+ case PrimitiveKind::Float32:
120
+ case PrimitiveKind::Float64: {
121
+ #ifdef __APPLE__
122
+ if (param.variadic)
123
+ break;
124
+ #endif
125
+
126
+ if (vec_avail) {
127
+ param.vec_count = 1;
128
+ vec_avail--;
129
+ }
130
+ } break;
151
131
  }
152
132
  }
153
133
 
@@ -157,62 +137,6 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
157
137
  return true;
158
138
  }
159
139
 
160
- static bool PushHFA(const Napi::Object &obj, const TypeInfo *type, uint8_t *dest)
161
- {
162
- Napi::Env env = obj.Env();
163
- InstanceData *instance = env.GetInstanceData<InstanceData>();
164
-
165
- RG_ASSERT(IsObject(obj));
166
- RG_ASSERT(IsHFA(type));
167
- RG_ASSERT(type->primitive == PrimitiveKind::Record);
168
- RG_ASSERT(AlignUp(dest, type->members[0].type->size) == dest);
169
-
170
- bool float32 = (type->members[0].type->primitive == PrimitiveKind::Float32);
171
-
172
- for (const RecordMember &member: type->members) {
173
- Napi::Value value = obj.Get(member.name);
174
-
175
- if (!value.IsNumber() && !value.IsBigInt()) {
176
- ThrowError<Napi::TypeError>(env, "Unexpected value %1 for member '%2', expected number", GetValueType(instance, value), member.name);
177
- return false;
178
- }
179
-
180
- if (float32) {
181
- *(float *)dest = CopyNumber<float>(value);
182
- } else {
183
- *(double *)dest = CopyNumber<double>(value);
184
- }
185
-
186
- dest += 8;
187
- }
188
-
189
- return true;
190
- }
191
-
192
- static Napi::Object PopHFA(napi_env env, const uint8_t *ptr, const TypeInfo *type)
193
- {
194
- RG_ASSERT(type->primitive == PrimitiveKind::Record);
195
- RG_ASSERT(IsHFA(type));
196
-
197
- Napi::Object obj = Napi::Object::New(env);
198
-
199
- bool float32 = (type->members[0].type->primitive == PrimitiveKind::Float32);
200
-
201
- for (const RecordMember &member: type->members) {
202
- if (float32) {
203
- float f = *(float *)ptr;
204
- obj.Set(member.name, Napi::Number::New(env, (double)f));
205
- } else {
206
- double d = *(double *)ptr;
207
- obj.Set(member.name, Napi::Number::New(env, d));
208
- }
209
-
210
- ptr += 8;
211
- }
212
-
213
- return obj;
214
- }
215
-
216
140
  bool CallData::Prepare(const Napi::CallbackInfo &info)
217
141
  {
218
142
  uint8_t *args_ptr = nullptr;
@@ -288,42 +212,6 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
288
212
  #endif
289
213
  }
290
214
  } break;
291
- case PrimitiveKind::Float32: {
292
- if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
293
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
294
- return false;
295
- }
296
-
297
- float f = CopyNumber<float>(value);
298
-
299
- if (RG_LIKELY(param.vec_count)) {
300
- memcpy(vec_ptr++, &f, 4);
301
- } else {
302
- args_ptr = AlignUp(args_ptr, 4);
303
- memcpy(args_ptr, &f, 4);
304
- #ifdef __APPLE__
305
- args_ptr += 4;
306
- #else
307
- args_ptr += 8;
308
- #endif
309
- }
310
- } break;
311
- case PrimitiveKind::Float64: {
312
- if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
313
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
314
- return false;
315
- }
316
-
317
- double d = CopyNumber<double>(value);
318
-
319
- if (RG_LIKELY(param.vec_count)) {
320
- memcpy(vec_ptr++, &d, 8);
321
- } else {
322
- args_ptr = AlignUp(args_ptr, 8);
323
- memcpy(args_ptr, &d, 8);
324
- args_ptr += 8;
325
- }
326
- } break;
327
215
  case PrimitiveKind::String: {
328
216
  const char *str;
329
217
  if (RG_LIKELY(value.IsString())) {
@@ -384,8 +272,11 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
384
272
  memset(ptr, 0, param.type->size);
385
273
  }
386
274
  if (param.directions & 2) {
387
- OutObject out = {obj, ptr, param.type->ref};
388
- out_objects.Append(out);
275
+ OutObject *out = out_objects.AppendDefault();
276
+
277
+ out->ref.Reset(obj, 1);
278
+ out->ptr = ptr;
279
+ out->type = param.type->ref;
389
280
  }
390
281
  } else if (IsNullOrUndefined(value)) {
391
282
  ptr = nullptr;
@@ -402,7 +293,6 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
402
293
  args_ptr += 8;
403
294
  }
404
295
  } break;
405
-
406
296
  case PrimitiveKind::Record: {
407
297
  if (RG_UNLIKELY(!IsObject(value))) {
408
298
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected object", GetValueType(instance, value), i + 1);
@@ -411,8 +301,8 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
411
301
 
412
302
  Napi::Object obj = value.As<Napi::Object>();
413
303
 
414
- if (param.vec_count) {
415
- if (!PushHFA(obj, param.type, (uint8_t *)vec_ptr))
304
+ if (param.vec_count) { // HFA
305
+ if (!PushObject(obj, param.type, (uint8_t *)vec_ptr, 8))
416
306
  return false;
417
307
  vec_ptr += param.vec_count;
418
308
  } else if (!param.use_memory) {
@@ -448,9 +338,49 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
448
338
  return false;
449
339
  }
450
340
  } break;
341
+ case PrimitiveKind::Array: { RG_UNREACHABLE(); } break;
342
+ case PrimitiveKind::Float32: {
343
+ if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
344
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
345
+ return false;
346
+ }
347
+
348
+ float f = CopyNumber<float>(value);
349
+
350
+ if (RG_LIKELY(param.vec_count)) {
351
+ memcpy(vec_ptr++, &f, 4);
352
+ } else {
353
+ args_ptr = AlignUp(args_ptr, 4);
354
+ memcpy(args_ptr, &f, 4);
355
+ #ifdef __APPLE__
356
+ args_ptr += 4;
357
+ #else
358
+ args_ptr += 8;
359
+ #endif
360
+ }
361
+ } break;
362
+ case PrimitiveKind::Float64: {
363
+ if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
364
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
365
+ return false;
366
+ }
367
+
368
+ double d = CopyNumber<double>(value);
369
+
370
+ if (RG_LIKELY(param.vec_count)) {
371
+ memcpy(vec_ptr++, &d, 8);
372
+ } else {
373
+ args_ptr = AlignUp(args_ptr, 8);
374
+ memcpy(args_ptr, &d, 8);
375
+ args_ptr += 8;
376
+ }
377
+ } break;
451
378
  }
452
379
  }
453
380
 
381
+ stack = MakeSpan(mem->stack.end(), old_stack_mem.end() - mem->stack.end());
382
+ heap = MakeSpan(old_heap_mem.ptr, mem->heap.ptr - old_heap_mem.ptr);
383
+
454
384
  return true;
455
385
  }
456
386
 
@@ -458,8 +388,8 @@ void CallData::Execute()
458
388
  {
459
389
  #define PERFORM_CALL(Suffix) \
460
390
  ([&]() { \
461
- auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func, GetSP()) \
462
- : ForwardCall ## Suffix(func->func, GetSP())); \
391
+ auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func, stack.ptr) \
392
+ : ForwardCall ## Suffix(func->func, stack.ptr)); \
463
393
  return ret; \
464
394
  })()
465
395
 
@@ -489,6 +419,7 @@ void CallData::Execute()
489
419
  PERFORM_CALL(GG);
490
420
  }
491
421
  } break;
422
+ case PrimitiveKind::Array: { RG_UNREACHABLE(); } break;
492
423
  case PrimitiveKind::Float32: { result.f = PERFORM_CALL(F); } break;
493
424
  case PrimitiveKind::Float64: { result.d = PERFORM_CALL(DDDD).d0; } break;
494
425
  }
@@ -498,8 +429,9 @@ void CallData::Execute()
498
429
 
499
430
  Napi::Value CallData::Complete()
500
431
  {
501
- for (const OutObject &obj: out_objects) {
502
- PopObject(obj.obj, obj.ptr, obj.type);
432
+ for (const OutObject &out: out_objects) {
433
+ Napi::Object obj = out.ref.Value().As<Napi::Object>();
434
+ PopObject(obj, out.ptr, out.type);
503
435
  }
504
436
 
505
437
  switch (func->ret.type->primitive) {
@@ -522,8 +454,8 @@ Napi::Value CallData::Complete()
522
454
  return external;
523
455
  } break;
524
456
  case PrimitiveKind::Record: {
525
- if (func->ret.vec_count) {
526
- Napi::Object obj = PopHFA(env, (const uint8_t *)&result.buf, func->ret.type);
457
+ if (func->ret.vec_count) { // HFA
458
+ Napi::Object obj = PopObject((const uint8_t *)&result.buf, func->ret.type, 8);
527
459
  return obj;
528
460
  } else {
529
461
  const uint8_t *ptr = return_ptr ? (const uint8_t *)return_ptr
@@ -533,6 +465,7 @@ Napi::Value CallData::Complete()
533
465
  return obj;
534
466
  }
535
467
  } break;
468
+ case PrimitiveKind::Array: { RG_UNREACHABLE(); } break;
536
469
  case PrimitiveKind::Float32: return Napi::Number::New(env, (double)result.f);
537
470
  case PrimitiveKind::Float64: return Napi::Number::New(env, result.d);
538
471
  }
@@ -98,13 +98,6 @@ static Size ClassifyType(const TypeInfo *type, Size offset, Span<RegisterClass>
98
98
  classes[0] = MergeClasses(classes[0], RegisterClass::Integer);
99
99
  return 1;
100
100
  } break;
101
-
102
- case PrimitiveKind::Float32:
103
- case PrimitiveKind::Float64: {
104
- classes[0] = MergeClasses(classes[0], RegisterClass::SSE);
105
- return 1;
106
- } break;
107
-
108
101
  case PrimitiveKind::Record: {
109
102
  if (type->size > 64) {
110
103
  classes[0] = MergeClasses(classes[0], RegisterClass::Memory);
@@ -119,6 +112,27 @@ static Size ClassifyType(const TypeInfo *type, Size offset, Span<RegisterClass>
119
112
 
120
113
  return (offset + 7) / 8;
121
114
  } break;
115
+ case PrimitiveKind::Array: {
116
+ if (type->size > 64) {
117
+ classes[0] = MergeClasses(classes[0], RegisterClass::Memory);
118
+ return 1;
119
+ }
120
+
121
+ Size len = type->size / type->ref->size;
122
+
123
+ for (Size i = 0; i < len; i++) {
124
+ Size start = offset / 8;
125
+ ClassifyType(type->ref, offset % 8, classes.Take(start, classes.len - start));
126
+ offset += type->ref->size;
127
+ }
128
+
129
+ return (offset + 7) / 8;
130
+ } break;
131
+ case PrimitiveKind::Float32:
132
+ case PrimitiveKind::Float64: {
133
+ classes[0] = MergeClasses(classes[0], RegisterClass::SSE);
134
+ return 1;
135
+ } break;
122
136
  }
123
137
 
124
138
  RG_UNREACHABLE();
@@ -308,8 +322,11 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
308
322
  memset(ptr, 0, param.type->size);
309
323
  }
310
324
  if (param.directions & 2) {
311
- OutObject out = {obj, ptr, param.type->ref};
312
- out_objects.Append(out);
325
+ OutObject *out = out_objects.AppendDefault();
326
+
327
+ out->ref.Reset(obj, 1);
328
+ out->ptr = ptr;
329
+ out->type = param.type->ref;
313
330
  }
314
331
  } else if (IsNullOrUndefined(value)) {
315
332
  ptr = nullptr;
@@ -367,6 +384,7 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
367
384
  args_ptr += AlignLen(param.type->size, 8);
368
385
  }
369
386
  } break;
387
+ case PrimitiveKind::Array: { RG_UNREACHABLE(); } break;
370
388
  case PrimitiveKind::Float32: {
371
389
  if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
372
390
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
@@ -402,6 +420,9 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
402
420
  }
403
421
  }
404
422
 
423
+ stack = MakeSpan(mem->stack.end(), old_stack_mem.end() - mem->stack.end());
424
+ heap = MakeSpan(old_heap_mem.ptr, mem->heap.ptr - old_heap_mem.ptr);
425
+
405
426
  return true;
406
427
  }
407
428
 
@@ -409,8 +430,8 @@ void CallData::Execute()
409
430
  {
410
431
  #define PERFORM_CALL(Suffix) \
411
432
  ([&]() { \
412
- auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func, GetSP()) \
413
- : ForwardCall ## Suffix(func->func, GetSP())); \
433
+ auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func, stack.ptr) \
434
+ : ForwardCall ## Suffix(func->func, stack.ptr)); \
414
435
  return ret; \
415
436
  })()
416
437
 
@@ -444,6 +465,7 @@ void CallData::Execute()
444
465
  memcpy_safe(&result.buf, &ret, RG_SIZE(ret));
445
466
  }
446
467
  } break;
468
+ case PrimitiveKind::Array: { RG_UNREACHABLE(); } break;
447
469
  case PrimitiveKind::Float32: { result.f = PERFORM_CALL(F); } break;
448
470
  case PrimitiveKind::Float64: { result.d = PERFORM_CALL(DG).xmm0; } break;
449
471
  }
@@ -453,8 +475,9 @@ void CallData::Execute()
453
475
 
454
476
  Napi::Value CallData::Complete()
455
477
  {
456
- for (const OutObject &obj: out_objects) {
457
- PopObject(obj.obj, obj.ptr, obj.type);
478
+ for (const OutObject &out: out_objects) {
479
+ Napi::Object obj = out.ref.Value().As<Napi::Object>();
480
+ PopObject(obj, out.ptr, out.type);
458
481
  }
459
482
 
460
483
  switch (func->ret.type->primitive) {
@@ -483,6 +506,7 @@ Napi::Value CallData::Complete()
483
506
  Napi::Object obj = PopObject(ptr, func->ret.type);
484
507
  return obj;
485
508
  } break;
509
+ case PrimitiveKind::Array: { RG_UNREACHABLE(); } break;
486
510
  case PrimitiveKind::Float32: return Napi::Number::New(env, (double)result.f);
487
511
  case PrimitiveKind::Float64: return Napi::Number::New(env, result.d);
488
512
  }
@@ -148,8 +148,11 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
148
148
  memset(ptr, 0, param.type->size);
149
149
  }
150
150
  if (param.directions & 2) {
151
- OutObject out = {obj, ptr, param.type->ref};
152
- out_objects.Append(out);
151
+ OutObject *out = out_objects.AppendDefault();
152
+
153
+ out->ref.Reset(obj, 1);
154
+ out->ptr = ptr;
155
+ out->type = param.type->ref;
153
156
  }
154
157
  } else if (IsNullOrUndefined(value)) {
155
158
  ptr = nullptr;
@@ -179,6 +182,7 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
179
182
  if (!PushObject(obj, param.type, ptr))
180
183
  return false;
181
184
  } break;
185
+ case PrimitiveKind::Array: { RG_UNREACHABLE(); } break;
182
186
  case PrimitiveKind::Float32: {
183
187
  if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
184
188
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
@@ -200,6 +204,9 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
200
204
  }
201
205
  }
202
206
 
207
+ stack = MakeSpan(mem->stack.end(), old_stack_mem.end() - mem->stack.end());
208
+ heap = MakeSpan(old_heap_mem.ptr, mem->heap.ptr - old_heap_mem.ptr);
209
+
203
210
  return true;
204
211
  }
205
212
 
@@ -207,8 +214,8 @@ void CallData::Execute()
207
214
  {
208
215
  #define PERFORM_CALL(Suffix) \
209
216
  ([&]() { \
210
- auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func, GetSP()) \
211
- : ForwardCall ## Suffix(func->func, GetSP())); \
217
+ auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func, stack.ptr) \
218
+ : ForwardCall ## Suffix(func->func, stack.ptr)); \
212
219
  return ret; \
213
220
  })()
214
221
 
@@ -227,6 +234,7 @@ void CallData::Execute()
227
234
  case PrimitiveKind::String16:
228
235
  case PrimitiveKind::Pointer:
229
236
  case PrimitiveKind::Record: { result.u64 = PERFORM_CALL(G); } break;
237
+ case PrimitiveKind::Array: { RG_UNREACHABLE(); } break;
230
238
  case PrimitiveKind::Float32: { result.f = PERFORM_CALL(F); } break;
231
239
  case PrimitiveKind::Float64: { result.d = PERFORM_CALL(D); } break;
232
240
  }
@@ -236,8 +244,9 @@ void CallData::Execute()
236
244
 
237
245
  Napi::Value CallData::Complete()
238
246
  {
239
- for (const OutObject &obj: out_objects) {
240
- PopObject(obj.obj, obj.ptr, obj.type);
247
+ for (const OutObject &out: out_objects) {
248
+ Napi::Object obj = out.ref.Value().As<Napi::Object>();
249
+ PopObject(obj, out.ptr, out.type);
241
250
  }
242
251
 
243
252
  switch (func->ret.type->primitive) {
@@ -266,6 +275,7 @@ Napi::Value CallData::Complete()
266
275
  Napi::Object obj = PopObject(ptr, func->ret.type);
267
276
  return obj;
268
277
  } break;
278
+ case PrimitiveKind::Array: { RG_UNREACHABLE(); } break;
269
279
  case PrimitiveKind::Float32: return Napi::Number::New(env, (double)result.f);
270
280
  case PrimitiveKind::Float64: return Napi::Number::New(env, result.d);
271
281
  }
package/src/abi_x86.cc CHANGED
@@ -192,8 +192,11 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
192
192
  memset(ptr, 0, param.type->size);
193
193
  }
194
194
  if (param.directions & 2) {
195
- OutObject out = {obj, ptr, param.type->ref};
196
- out_objects.Append(out);
195
+ OutObject *out = out_objects.AppendDefault();
196
+
197
+ out->ref.Reset(obj, 1);
198
+ out->ptr = ptr;
199
+ out->type = param.type->ref;
197
200
  }
198
201
  } else if (IsNullOrUndefined(value)) {
199
202
  ptr = nullptr;
@@ -223,6 +226,7 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
223
226
  args_ptr = (uint32_t *)AlignUp(ptr + param.type->size, 4);
224
227
  }
225
228
  } break;
229
+ case PrimitiveKind::Array: { RG_UNREACHABLE(); } break;
226
230
  case PrimitiveKind::Float32: {
227
231
  if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
228
232
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
@@ -245,6 +249,9 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
245
249
  }
246
250
  }
247
251
 
252
+ stack = MakeSpan(mem->stack.end(), old_stack_mem.end() - mem->stack.end());
253
+ heap = MakeSpan(old_heap_mem.ptr, mem->heap.ptr - old_heap_mem.ptr);
254
+
248
255
  return true;
249
256
  }
250
257
 
@@ -252,8 +259,8 @@ void CallData::Execute()
252
259
  {
253
260
  #define PERFORM_CALL(Suffix) \
254
261
  ([&]() { \
255
- auto ret = (func->convention == CallConvention::Fastcall ? ForwardCallR ## Suffix(func->func, GetSP()) \
256
- : ForwardCall ## Suffix(func->func, GetSP())); \
262
+ auto ret = (func->convention == CallConvention::Fastcall ? ForwardCallR ## Suffix(func->func, stack.ptr) \
263
+ : ForwardCall ## Suffix(func->func, stack.ptr)); \
257
264
  return ret; \
258
265
  })()
259
266
 
@@ -273,6 +280,7 @@ void CallData::Execute()
273
280
  case PrimitiveKind::String16:
274
281
  case PrimitiveKind::Pointer:
275
282
  case PrimitiveKind::Record: { result.u64 = PERFORM_CALL(G); } break;
283
+ case PrimitiveKind::Array: { RG_UNREACHABLE(); } break;
276
284
  case PrimitiveKind::Float32: { result.f = PERFORM_CALL(F); } break;
277
285
  case PrimitiveKind::Float64: { result.d = PERFORM_CALL(D); } break;
278
286
  }
@@ -282,8 +290,9 @@ void CallData::Execute()
282
290
 
283
291
  Napi::Value CallData::Complete()
284
292
  {
285
- for (const OutObject &obj: out_objects) {
286
- PopObject(obj.obj, obj.ptr, obj.type);
293
+ for (const OutObject &out: out_objects) {
294
+ Napi::Object obj = out.ref.Value().As<Napi::Object>();
295
+ PopObject(obj, out.ptr, out.type);
287
296
  }
288
297
 
289
298
  switch (func->ret.type->primitive) {
@@ -312,6 +321,7 @@ Napi::Value CallData::Complete()
312
321
  Napi::Object obj = PopObject(ptr, func->ret.type);
313
322
  return obj;
314
323
  } break;
324
+ case PrimitiveKind::Array: { RG_UNREACHABLE(); } break;
315
325
  case PrimitiveKind::Float32: return Napi::Number::New(env, (double)result.f);
316
326
  case PrimitiveKind::Float64: return Napi::Number::New(env, result.d);
317
327
  }