koffi 1.2.0-alpha.3 → 1.2.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/abi_arm64.cc CHANGED
@@ -209,7 +209,7 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
209
209
 
210
210
  bool CallData::Prepare(const Napi::CallbackInfo &info)
211
211
  {
212
- uint8_t *args_ptr = nullptr;
212
+ uint64_t *args_ptr = nullptr;
213
213
  uint64_t *gpr_ptr = nullptr;
214
214
  uint64_t *vec_ptr = nullptr;
215
215
 
@@ -244,16 +244,16 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
244
244
 
245
245
  bool b = value.As<Napi::Boolean>();
246
246
 
247
+ #ifdef __APPLE__
247
248
  if (RG_LIKELY(param.gpr_count)) {
248
249
  *(gpr_ptr++) = (uint64_t)b;
249
250
  } else {
250
- *args_ptr = (uint8_t)b;
251
- #ifdef __APPLE__
252
- args_ptr++;
251
+ *(uint8_t *)args_ptr = b;
252
+ args_ptr = (uint64_t *)((uint8_t *)args_ptr + 1);
253
+ }
253
254
  #else
254
- args_ptr += 8;
255
+ *((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint64_t)b;
255
256
  #endif
256
- }
257
257
  } break;
258
258
  case PrimitiveKind::Int8:
259
259
  case PrimitiveKind::UInt8:
@@ -269,17 +269,17 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
269
269
 
270
270
  int64_t v = CopyNumber<int64_t>(value);
271
271
 
272
+ #ifdef __APPLE__
272
273
  if (RG_LIKELY(param.gpr_count)) {
273
274
  *(int64_t *)(gpr_ptr++) = v;
274
275
  } else {
275
276
  args_ptr = AlignUp(args_ptr, param.type->align);
276
277
  *(int64_t *)args_ptr = v;
277
- #ifdef __APPLE__
278
- args_ptr += param.type->size;
278
+ args_ptr = (uint64_t *)((uint8_t *)args_ptr + param.type->size);
279
+ }
279
280
  #else
280
- args_ptr += 8;
281
+ *(int64_t *)((param.gpr_count ? gpr_ptr : args_ptr)++) = v;
281
282
  #endif
282
- }
283
283
  } break;
284
284
  case PrimitiveKind::UInt64: {
285
285
  if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
@@ -289,13 +289,10 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
289
289
 
290
290
  uint64_t v = CopyNumber<uint64_t>(value);
291
291
 
292
- if (RG_LIKELY(param.gpr_count)) {
293
- *(gpr_ptr++) = v;
294
- } else {
295
- args_ptr = AlignUp(args_ptr, param.type->align);
296
- *(uint64_t *)args_ptr = v;
297
- args_ptr += 8;
298
- }
292
+ #ifdef __APPLE__
293
+ args_ptr = param.gpr_count ? args_ptr : AlignUp(args_ptr, 8);
294
+ #endif
295
+ *((param.gpr_count ? gpr_ptr : args_ptr)++) = v;
299
296
  } break;
300
297
  case PrimitiveKind::String: {
301
298
  const char *str;
@@ -310,13 +307,10 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
310
307
  return false;
311
308
  }
312
309
 
313
- if (RG_LIKELY(param.gpr_count)) {
314
- *(gpr_ptr++) = (uint64_t)str;
315
- } else {
316
- args_ptr = AlignUp(args_ptr, 8);
317
- *(uint64_t *)args_ptr = (uint64_t)str;
318
- args_ptr += 8;
319
- }
310
+ #ifdef __APPLE__
311
+ args_ptr = param.gpr_count ? args_ptr : AlignUp(args_ptr, 8);
312
+ #endif
313
+ *(const char **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str;
320
314
  } break;
321
315
  case PrimitiveKind::String16: {
322
316
  const char16_t *str16;
@@ -331,13 +325,10 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
331
325
  return false;
332
326
  }
333
327
 
334
- if (RG_LIKELY(param.gpr_count)) {
335
- *(gpr_ptr++) = (uint64_t)str16;
336
- } else {
337
- args_ptr = AlignUp(args_ptr, 8);
338
- *(uint64_t *)args_ptr = (uint64_t)str16;
339
- args_ptr += 8;
340
- }
328
+ #ifdef __APPLE__
329
+ args_ptr = param.gpr_count ? args_ptr : AlignUp(args_ptr, 8);
330
+ #endif
331
+ *(const char16_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str16;
341
332
  } break;
342
333
  case PrimitiveKind::Pointer: {
343
334
  uint8_t *ptr;
@@ -370,13 +361,10 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
370
361
  return false;
371
362
  }
372
363
 
373
- if (RG_LIKELY(param.gpr_count)) {
374
- *(gpr_ptr++) = (uint64_t)ptr;
375
- } else {
376
- args_ptr = AlignUp(args_ptr, 8);
377
- *(uint64_t *)args_ptr = (uint64_t)ptr;
378
- args_ptr += 8;
379
- }
364
+ #ifdef __APPLE__
365
+ args_ptr = param.gpr_count ? args_ptr : AlignUp(args_ptr, 8);
366
+ #endif
367
+ *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
380
368
  } break;
381
369
  case PrimitiveKind::Record: {
382
370
  if (RG_UNLIKELY(!IsObject(value))) {
@@ -398,10 +386,12 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
398
386
  return false;
399
387
  gpr_ptr += param.gpr_count;
400
388
  } else if (param.type->size) {
389
+ #ifdef __APPLE__
401
390
  args_ptr = AlignUp(args_ptr, 8);
402
- if (!PushObject(obj, param.type, args_ptr))
391
+ #endif
392
+ if (!PushObject(obj, param.type, (uint8_t *)args_ptr))
403
393
  return false;
404
- args_ptr += AlignLen(param.type->size, 8);
394
+ args_ptr += (param.type->size + 7) / 8;
405
395
  }
406
396
  } else {
407
397
  uint8_t *ptr;
@@ -412,11 +402,12 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
412
402
  RG_ASSERT(param.gpr_count == 1);
413
403
  RG_ASSERT(param.vec_count == 0);
414
404
 
415
- *(gpr_ptr++) = (uint64_t)ptr;
405
+ *(uint8_t **)(gpr_ptr++) = ptr;
416
406
  } else {
407
+ #ifdef __APPLE__
417
408
  args_ptr = AlignUp(args_ptr, 8);
418
- *(uint8_t **)args_ptr = ptr;
419
- args_ptr += 8;
409
+ #endif
410
+ *(uint8_t **)(args_ptr++) = ptr;
420
411
  }
421
412
 
422
413
  if (!PushObject(obj, param.type, ptr))
@@ -433,14 +424,16 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
433
424
  float f = CopyNumber<float>(value);
434
425
 
435
426
  if (RG_LIKELY(param.vec_count)) {
427
+ memset((uint8_t *)vec_ptr + 4, 0, 4);
436
428
  *(float *)(vec_ptr++) = f;
437
429
  } else {
430
+ #ifdef __APPLE__
438
431
  args_ptr = AlignUp(args_ptr, 4);
439
432
  *(float *)args_ptr = f;
440
- #ifdef __APPLE__
441
- args_ptr += 4;
433
+ args_ptr = (uint64_t *)((uint8_t *)args_ptr + 4);
442
434
  #else
443
- args_ptr += 8;
435
+ memset((uint8_t *)args_ptr + 4, 0, 4);
436
+ *(float *)(args_ptr++) = f;
444
437
  #endif
445
438
  }
446
439
  } break;
@@ -455,9 +448,10 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
455
448
  if (RG_LIKELY(param.vec_count)) {
456
449
  *(double *)(vec_ptr++) = d;
457
450
  } else {
451
+ #ifdef __APPLE__
458
452
  args_ptr = AlignUp(args_ptr, 8);
459
- *(double *)args_ptr = d;
460
- args_ptr += 8;
453
+ #endif
454
+ *(double *)(args_ptr++) = d;
461
455
  }
462
456
  } break;
463
457
  case PrimitiveKind::Callback: {
@@ -480,13 +474,10 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
480
474
  return false;
481
475
  }
482
476
 
483
- if (RG_LIKELY(param.gpr_count)) {
484
- *(gpr_ptr++) = (uint64_t)ptr;
485
- } else {
486
- args_ptr = AlignUp(args_ptr, 8);
487
- *(uint64_t *)args_ptr = (uint64_t)ptr;
488
- args_ptr += 8;
489
- }
477
+ #ifdef __APPLE__
478
+ args_ptr = param.gpr_count ? args_ptr : AlignUp(args_ptr, 8);
479
+ #endif
480
+ *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
490
481
  } break;
491
482
  }
492
483
  }
@@ -977,6 +968,8 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegister
977
968
  }
978
969
 
979
970
  float f = CopyNumber<float>(value);
971
+
972
+ memset((uint8_t *)&out_reg->d0 + 4, 0, 4);
980
973
  memcpy(&out_reg->d0, &f, 4);
981
974
  } break;
982
975
  case PrimitiveKind::Float64: {
@@ -287,8 +287,8 @@ SYMBOL(TrampolineX15):
287
287
  trampoline_vec 15
288
288
 
289
289
  # When a callback is relayed, Koffi will call into Node.js and V8 to execute Javascript.
290
- # The propblem is that we're still running on the separate Koffi stack, and V8 will
291
- # preobably misdetect this as a "stack overflow". We have to restore the old
290
+ # The problem is that we're still running on the separate Koffi stack, and V8 will
291
+ # probably misdetect this as a "stack overflow". We have to restore the old
292
292
  # stack pointer, call Node.js/V8 and go back to ours.
293
293
  # The first three parameters (x0, x1, x2) are passed through untouched.
294
294
  SYMBOL(CallSwitchStack):
@@ -302,8 +302,8 @@ TrampolineX15 PROC
302
302
  ENDP
303
303
 
304
304
  ; When a callback is relayed, Koffi will call into Node.js and V8 to execute Javascript.
305
- ; The propblem is that we're still running on the separate Koffi stack, and V8 will
306
- ; preobably misdetect this as a "stack overflow". We have to restore the old
305
+ ; The problem is that we're still running on the separate Koffi stack, and V8 will
306
+ ; probably misdetect this as a "stack overflow". We have to restore the old
307
307
  ; stack pointer, call Node.js/V8 and go back to ours.
308
308
  ; The first three parameters (x0, x1, x2) are passed through untouched.
309
309
  CallSwitchStack PROC
@@ -300,8 +300,8 @@ TrampolineX15:
300
300
  trampoline_vec 15
301
301
 
302
302
  # When a callback is relayed, Koffi will call into Node.js and V8 to execute Javascript.
303
- # The propblem is that we're still running on the separate Koffi stack, and V8 will
304
- # preobably misdetect this as a "stack overflow". We have to restore the old
303
+ # The problem is that we're still running on the separate Koffi stack, and V8 will
304
+ # probably misdetect this as a "stack overflow". We have to restore the old
305
305
  # stack pointer, call Node.js/V8 and go back to ours.
306
306
  # The first three parameters (a0, a1, a2) are passed through untouched.
307
307
  CallSwitchStack:
@@ -417,7 +417,10 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
417
417
  }
418
418
 
419
419
  float f = CopyNumber<float>(value);
420
- *(float *)((param.xmm_count ? xmm_ptr : args_ptr)++) = f;
420
+ uint64_t *ptr = (param.xmm_count ? xmm_ptr : args_ptr)++;
421
+
422
+ memset((uint8_t *)ptr + 4, 0, 4);
423
+ *(float *)ptr = f;
421
424
  } break;
422
425
  case PrimitiveKind::Float64: {
423
426
  if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
@@ -838,6 +841,8 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegister
838
841
  }
839
842
 
840
843
  float f = CopyNumber<float>(value);
844
+
845
+ memset((uint8_t *)&out_reg->xmm0 + 4, 0, 4);
841
846
  memcpy(&out_reg->xmm0, &f, 4);
842
847
  } break;
843
848
  case PrimitiveKind::Float64: {
@@ -321,8 +321,8 @@ SYMBOL(TrampolineX15):
321
321
  trampoline_xmm 15
322
322
 
323
323
  # When a callback is relayed, Koffi will call into Node.js and V8 to execute Javascript.
324
- # The propblem is that we're still running on the separate Koffi stack, and V8 will
325
- # preobably misdetect this as a "stack overflow". We have to restore the old
324
+ # The problem is that we're still running on the separate Koffi stack, and V8 will
325
+ # probably misdetect this as a "stack overflow". We have to restore the old
326
326
  # stack pointer, call Node.js/V8 and go back to ours.
327
327
  # The first three parameters (rdi, rsi, rdx) are passed through untouched.
328
328
  SYMBOL(CallSwitchStack):
@@ -244,6 +244,8 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
244
244
  }
245
245
 
246
246
  float f = CopyNumber<float>(value);
247
+
248
+ memset((uint8_t *)args_ptr + 4, 0, 4);
247
249
  *(float *)(args_ptr++) = f;
248
250
  } break;
249
251
  case PrimitiveKind::Float64: {
@@ -622,6 +624,8 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegister
622
624
  }
623
625
 
624
626
  float f = CopyNumber<float>(value);
627
+
628
+ memset((uint8_t *)&out_reg->xmm0 + 4, 0, 4);
625
629
  memcpy(&out_reg->xmm0, &f, 4);
626
630
  } break;
627
631
  case PrimitiveKind::Float64: {
@@ -164,7 +164,7 @@ trampoline macro ID
164
164
  lea r8, qword ptr [rsp+128]
165
165
  lea r9, qword ptr [rsp+96]
166
166
  call RelayCallBack
167
- mov qword ptr [rsp+96], rax
167
+ mov rax, qword ptr [rsp+96]
168
168
  add rsp, 120
169
169
  ret
170
170
  endm
@@ -188,8 +188,8 @@ trampoline_xmm macro ID
188
188
  lea r8, qword ptr [rsp+128]
189
189
  lea r9, qword ptr [rsp+96]
190
190
  call RelayCallBack
191
- mov qword ptr [rsp+96], rax
192
- movsd qword ptr [rsp+104], xmm0
191
+ mov rax, qword ptr [rsp+96]
192
+ movsd xmm0, qword ptr [rsp+104]
193
193
  add rsp, 120
194
194
  ret
195
195
  endm
@@ -293,8 +293,8 @@ TrampolineX15 proc frame
293
293
  TrampolineX15 endp
294
294
 
295
295
  ; When a callback is relayed, Koffi will call into Node.js and V8 to execute Javascript.
296
- ; The propblem is that we're still running on the separate Koffi stack, and V8 will
297
- ; preobably misdetect this as a "stack overflow". We have to restore the old
296
+ ; The problem is that we're still running on the separate Koffi stack, and V8 will
297
+ ; probably misdetect this as a "stack overflow". We have to restore the old
298
298
  ; stack pointer, call Node.js/V8 and go back to ours.
299
299
  ; The first three parameters (rcx, rdx, r8) are passed through untouched.
300
300
  CallSwitchStack proc frame
package/src/abi_x86.cc CHANGED
@@ -442,7 +442,9 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegister
442
442
  used_trampolines &= ~(1u << idx);
443
443
 
444
444
  uint32_t *args_ptr = (uint32_t *)caller_sp;
445
+
445
446
  uint8_t *return_ptr = !proto->ret.trivial ? (uint8_t *)args_ptr[0] : nullptr;
447
+ args_ptr += !proto->ret.trivial;
446
448
 
447
449
  LocalArray<napi_value, MaxParameters> arguments;
448
450
 
package/src/abi_x86_fwd.S CHANGED
@@ -162,8 +162,8 @@ ForwardCallRD:
162
162
  call GetEIP
163
163
  addl $_GLOBAL_OFFSET_TABLE_, %ecx
164
164
  call *RelayCallBack@GOT(%ecx)
165
- cmpb $1, 36(%esp)
166
- je 2f
165
+ cmpb $0, 36(%esp)
166
+ jne 2f
167
167
  1:
168
168
  flds 32(%esp)
169
169
  jmp 3f
@@ -249,8 +249,8 @@ TrampolineX15:
249
249
  trampoline_x87 15
250
250
 
251
251
  # When a callback is relayed, Koffi will call into Node.js and V8 to execute Javascript.
252
- # The propblem is that we're still running on the separate Koffi stack, and V8 will
253
- # preobably misdetect this as a "stack overflow". We have to restore the old
252
+ # The problem is that we're still running on the separate Koffi stack, and V8 will
253
+ # probably misdetect this as a "stack overflow". We have to restore the old
254
254
  # stack pointer, call Node.js/V8 and go back to ours.
255
255
  CallSwitchStack:
256
256
  .cfi_startproc
@@ -158,8 +158,8 @@ trampoline_x87 macro ID
158
158
  lea eax, dword ptr [esp+16]
159
159
  mov dword ptr [esp+12], eax
160
160
  call RelayCallBack
161
- cmp byte ptr[esp+36], 1
162
- je l2
161
+ cmp byte ptr[esp+36], 0
162
+ jne l2
163
163
  l1:
164
164
  fld dword ptr [esp+32]
165
165
  jmp l3
@@ -271,8 +271,8 @@ TrampolineX15 proc
271
271
  TrampolineX15 endp
272
272
 
273
273
  ; When a callback is relayed, Koffi will call into Node.js and V8 to execute Javascript.
274
- ; The propblem is that we're still running on the separate Koffi stack, and V8 will
275
- ; preobably misdetect this as a "stack overflow". We have to restore the old
274
+ ; The problem is that we're still running on the separate Koffi stack, and V8 will
275
+ ; probably misdetect this as a "stack overflow". We have to restore the old
276
276
  ; stack pointer, call Node.js/V8 and go back to ours.
277
277
  CallSwitchStack proc
278
278
  endbr32
package/src/call.cc CHANGED
@@ -116,11 +116,13 @@ const char16_t *CallData::PushString16(const Napi::Value &value)
116
116
  return buf.ptr;
117
117
  }
118
118
 
119
- bool CallData::PushObject(const Napi::Object &obj, const TypeInfo *type, uint8_t *dest, int16_t realign)
119
+ bool CallData::PushObject(const Napi::Object &obj, const TypeInfo *type, uint8_t *origin, int16_t realign)
120
120
  {
121
121
  RG_ASSERT(IsObject(obj));
122
122
  RG_ASSERT(type->primitive == PrimitiveKind::Record);
123
123
 
124
+ Size offset = 0;
125
+
124
126
  for (const RecordMember &member: type->members) {
125
127
  Napi::Value value = obj.Get(member.name);
126
128
 
@@ -130,7 +132,9 @@ bool CallData::PushObject(const Napi::Object &obj, const TypeInfo *type, uint8_t
130
132
  }
131
133
 
132
134
  int16_t align = std::max(member.align, realign);
133
- dest = AlignUp(dest, align);
135
+ offset = AlignLen(offset, align);
136
+
137
+ uint8_t *dest = origin + offset;
134
138
 
135
139
  switch (member.type->primitive) {
136
140
  case PrimitiveKind::Void: { RG_UNREACHABLE(); } break;
@@ -313,18 +317,19 @@ bool CallData::PushObject(const Napi::Object &obj, const TypeInfo *type, uint8_t
313
317
  } break;
314
318
  }
315
319
 
316
- dest += member.type->size;
320
+ offset += member.type->size;
317
321
  }
318
322
 
319
323
  return true;
320
324
  }
321
325
 
322
- bool CallData::PushArray(const Napi::Value &obj, const TypeInfo *type, uint8_t *dest, int16_t realign)
326
+ bool CallData::PushArray(const Napi::Value &obj, const TypeInfo *type, uint8_t *origin, int16_t realign)
323
327
  {
324
328
  RG_ASSERT(obj.IsArray() || obj.IsTypedArray() || obj.IsString());
325
329
  RG_ASSERT(type->primitive == PrimitiveKind::Array);
326
330
 
327
331
  uint32_t len = type->size / type->ref->size;
332
+ Size offset = 0;
328
333
 
329
334
  if (obj.IsArray()) {
330
335
  Napi::Array array = obj.As<Napi::Array>();
@@ -340,7 +345,9 @@ bool CallData::PushArray(const Napi::Value &obj, const TypeInfo *type, uint8_t *
340
345
  Napi::Value value = array[i]; \
341
346
  \
342
347
  int16_t align = std::max(type->ref->align, realign); \
343
- dest = AlignUp(dest, align); \
348
+ \
349
+ offset = AlignLen(offset, align); \
350
+ uint8_t *dest = origin + offset; \
344
351
  \
345
352
  if (RG_UNLIKELY(!(Check))) { \
346
353
  ThrowError<Napi::TypeError>(env, "Unexpected value %1 in array, expected %2", GetValueType(instance, value), (Expected)); \
@@ -349,7 +356,7 @@ bool CallData::PushArray(const Napi::Value &obj, const TypeInfo *type, uint8_t *
349
356
  \
350
357
  GetCode \
351
358
  \
352
- dest += type->ref->size; \
359
+ offset += type->ref->size; \
353
360
  } \
354
361
  } while (false)
355
362
 
@@ -467,7 +474,9 @@ bool CallData::PushArray(const Napi::Value &obj, const TypeInfo *type, uint8_t *
467
474
  Napi::Value value = array[i];
468
475
 
469
476
  int16_t align = std::max(type->ref->align, realign);
470
- dest = AlignUp(dest, align);
477
+ offset = AlignLen(offset, align);
478
+
479
+ uint8_t *dest = origin + offset;
471
480
 
472
481
  void *ptr;
473
482
 
@@ -491,7 +500,7 @@ bool CallData::PushArray(const Napi::Value &obj, const TypeInfo *type, uint8_t *
491
500
 
492
501
  *(void **)dest = ptr;
493
502
 
494
- dest += type->ref->size;
503
+ offset += type->ref->size;
495
504
  }
496
505
  } break;
497
506
  }
@@ -526,20 +535,22 @@ bool CallData::PushArray(const Napi::Value &obj, const TypeInfo *type, uint8_t *
526
535
 
527
536
  for (uint32_t i = 0; i < len; i++) {
528
537
  int16_t align = std::max(type->ref->align, realign);
529
- dest = AlignUp(dest, align);
538
+ offset = AlignLen(offset, align);
539
+
540
+ uint8_t *dest = origin + offset;
530
541
 
531
542
  memcpy(dest, buf + i * type->ref->size, type->ref->size);
532
543
 
533
- dest += type->ref->size;
544
+ offset += type->ref->size;
534
545
  }
535
546
  } else if (obj.IsString()) {
536
547
  size_t encoded = 0;
537
548
 
538
549
  if (type->ref->primitive == PrimitiveKind::Int8 || type->ref->primitive == PrimitiveKind::UInt8) {
539
- napi_status status = napi_get_value_string_utf8(env, obj, (char *)dest, type->size, &encoded);
550
+ napi_status status = napi_get_value_string_utf8(env, obj, (char *)origin, type->size, &encoded);
540
551
  RG_ASSERT(status == napi_ok);
541
552
  } else if (type->ref->primitive == PrimitiveKind::Int16 || type->ref->primitive == PrimitiveKind::UInt16) {
542
- napi_status status = napi_get_value_string_utf16(env, obj, (char16_t *)dest, type->size / 2, &encoded);
553
+ napi_status status = napi_get_value_string_utf16(env, obj, (char16_t *)origin, type->size / 2, &encoded);
543
554
  RG_ASSERT(status == napi_ok);
544
555
 
545
556
  encoded *= 2;
@@ -548,7 +559,7 @@ bool CallData::PushArray(const Napi::Value &obj, const TypeInfo *type, uint8_t *
548
559
  return false;
549
560
  }
550
561
 
551
- memset_safe(dest + encoded, 0, type->size - encoded);
562
+ memset_safe(origin + encoded, 0, type->size - encoded);
552
563
  } else {
553
564
  RG_UNREACHABLE();
554
565
  }
@@ -574,16 +585,20 @@ Size CallData::ReserveTrampoline(const FunctionInfo *proto, Napi::Function func)
574
585
  return idx;
575
586
  }
576
587
 
577
- void CallData::PopObject(Napi::Object obj, const uint8_t *src, const TypeInfo *type, int16_t realign)
588
+ void CallData::PopObject(Napi::Object obj, const uint8_t *origin, const TypeInfo *type, int16_t realign)
578
589
  {
579
590
  Napi::Env env = obj.Env();
580
591
  InstanceData *instance = env.GetInstanceData<InstanceData>();
581
592
 
582
593
  RG_ASSERT(type->primitive == PrimitiveKind::Record);
583
594
 
595
+ Size offset = 0;
596
+
584
597
  for (const RecordMember &member: type->members) {
585
598
  int16_t align = std::max(realign, member.align);
586
- src = AlignUp(src, align);
599
+ offset = AlignLen(offset, align);
600
+
601
+ const uint8_t *src = origin + offset;
587
602
 
588
603
  switch (member.type->primitive) {
589
604
  case PrimitiveKind::Void: { RG_UNREACHABLE(); } break;
@@ -663,18 +678,18 @@ void CallData::PopObject(Napi::Object obj, const uint8_t *src, const TypeInfo *t
663
678
  } break;
664
679
  }
665
680
 
666
- src += member.type->size;
681
+ offset += member.type->size;
667
682
  }
668
683
  }
669
684
 
670
- Napi::Object CallData::PopObject(const uint8_t *src, const TypeInfo *type, int16_t realign)
685
+ Napi::Object CallData::PopObject(const uint8_t *origin, const TypeInfo *type, int16_t realign)
671
686
  {
672
687
  Napi::Object obj = Napi::Object::New(env);
673
- PopObject(obj, src, type, realign);
688
+ PopObject(obj, origin, type, realign);
674
689
  return obj;
675
690
  }
676
691
 
677
- Size WideStringLength(const char16_t *str16, Size max)
692
+ static Size WideStringLength(const char16_t *str16, Size max)
678
693
  {
679
694
  Size len = 0;
680
695
 
@@ -685,13 +700,14 @@ Size WideStringLength(const char16_t *str16, Size max)
685
700
  return len;
686
701
  }
687
702
 
688
- Napi::Value CallData::PopArray(const uint8_t *src, const TypeInfo *type, int16_t realign)
703
+ Napi::Value CallData::PopArray(const uint8_t *origin, const TypeInfo *type, int16_t realign)
689
704
  {
690
705
  InstanceData *instance = env.GetInstanceData<InstanceData>();
691
706
 
692
707
  RG_ASSERT(type->primitive == PrimitiveKind::Array);
693
708
 
694
709
  uint32_t len = type->size / type->ref->size;
710
+ Size offset = 0;
695
711
 
696
712
  #define POP_ARRAY(SetCode) \
697
713
  do { \
@@ -699,11 +715,13 @@ Napi::Value CallData::PopArray(const uint8_t *src, const TypeInfo *type, int16_t
699
715
  \
700
716
  for (uint32_t i = 0; i < len; i++) { \
701
717
  int16_t align = std::max(realign, type->ref->align); \
702
- src = AlignUp(src, align); \
718
+ offset = AlignLen(offset, align); \
719
+ \
720
+ const uint8_t *src = origin + offset; \
703
721
  \
704
722
  SetCode \
705
723
  \
706
- src += type->ref->size; \
724
+ offset += type->ref->size; \
707
725
  } \
708
726
  \
709
727
  return array; \
@@ -720,12 +738,14 @@ Napi::Value CallData::PopArray(const uint8_t *src, const TypeInfo *type, int16_t
720
738
  \
721
739
  for (uint32_t i = 0; i < len; i++) { \
722
740
  int16_t align = std::max(realign, type->ref->align); \
723
- src = AlignUp(src, align); \
741
+ offset = AlignLen(offset, align); \
742
+ \
743
+ const uint8_t *src = origin + offset; \
724
744
  \
725
745
  CType f = *(CType *)src; \
726
746
  array[i] = f; \
727
747
  \
728
- src += type->ref->size; \
748
+ offset += type->ref->size; \
729
749
  } \
730
750
  \
731
751
  return array; \
@@ -745,7 +765,7 @@ Napi::Value CallData::PopArray(const uint8_t *src, const TypeInfo *type, int16_t
745
765
  if (type->hint == TypeInfo::ArrayHint::String) {
746
766
  RG_ASSERT(!realign);
747
767
 
748
- const char *ptr = (const char *)src;
768
+ const char *ptr = (const char *)origin;
749
769
  size_t count = strnlen(ptr, (size_t)len);
750
770
 
751
771
  Napi::String str = Napi::String::New(env, ptr, count);
@@ -758,7 +778,7 @@ Napi::Value CallData::PopArray(const uint8_t *src, const TypeInfo *type, int16_t
758
778
  if (type->hint == TypeInfo::ArrayHint::String) {
759
779
  RG_ASSERT(!realign);
760
780
 
761
- const char *ptr = (const char *)src;
781
+ const char *ptr = (const char *)origin;
762
782
  size_t count = strnlen(ptr, (size_t)len);
763
783
 
764
784
  Napi::String str = Napi::String::New(env, ptr, count);
@@ -771,7 +791,7 @@ Napi::Value CallData::PopArray(const uint8_t *src, const TypeInfo *type, int16_t
771
791
  if (type->hint == TypeInfo::ArrayHint::String) {
772
792
  RG_ASSERT(!realign);
773
793
 
774
- const char16_t *ptr = (const char16_t *)src;
794
+ const char16_t *ptr = (const char16_t *)origin;
775
795
  Size count = WideStringLength(ptr, len);
776
796
 
777
797
  Napi::String str = Napi::String::New(env, ptr, count);
@@ -784,7 +804,7 @@ Napi::Value CallData::PopArray(const uint8_t *src, const TypeInfo *type, int16_t
784
804
  if (type->hint == TypeInfo::ArrayHint::String) {
785
805
  RG_ASSERT(!realign);
786
806
 
787
- const char16_t *ptr = (const char16_t *)src;
807
+ const char16_t *ptr = (const char16_t *)origin;
788
808
  Size count = WideStringLength(ptr, len);
789
809
 
790
810
  Napi::String str = Napi::String::New(env, ptr, count);
@@ -856,24 +876,7 @@ Napi::Value CallData::PopArray(const uint8_t *src, const TypeInfo *type, int16_t
856
876
  RG_UNREACHABLE();
857
877
  }
858
878
 
859
- static void DumpMemory(const char *type, Span<const uint8_t> bytes)
860
- {
861
- if (bytes.len) {
862
- PrintLn(stderr, "%1 at 0x%2 (%3):", type, bytes.ptr, FmtMemSize(bytes.len));
863
-
864
- for (const uint8_t *ptr = bytes.begin(); ptr < bytes.end();) {
865
- Print(stderr, " [0x%1 %2 %3] ", FmtArg(ptr).Pad0(-16),
866
- FmtArg((ptr - bytes.begin()) / sizeof(void *)).Pad(-4),
867
- FmtArg(ptr - bytes.begin()).Pad(-4));
868
- for (int i = 0; ptr < bytes.end() && i < (int)sizeof(void *); i++, ptr++) {
869
- Print(stderr, " %1", FmtHex(*ptr).Pad0(-2));
870
- }
871
- PrintLn(stderr);
872
- }
873
- }
874
- }
875
-
876
- void CallData::DumpDebug() const
879
+ void CallData::DumpForward() const
877
880
  {
878
881
  PrintLn(stderr, "%!..+---- %1 (%2) ----%!0", func->name, CallConventionNames[(int)func->convention]);
879
882