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/README.md CHANGED
@@ -18,13 +18,12 @@
18
18
 
19
19
  # Introduction
20
20
 
21
- Koffi is a fast and easy-to-use C FFI module for Node.js, with support for primitive and aggregate data types (structs and fixed-size arrays), both by reference (pointer) and by value.
21
+ Koffi is a fast and easy-to-use C FFI module for Node.js, featuring:
22
22
 
23
- The following features are planned in the near future:
24
-
25
- * 1.2: C to JS callbacks (⚠️ partially working in master branch)
26
- * 1.3: Real-world examples, optimize passing of structs and arrays
27
- * 1.4: Type parser, unions
23
+ * Low-overhead and fast performance (see [benchmarks](#benchmarks))
24
+ * Support for primitive and aggregate data types (structs and fixed-size arrays), both by reference (pointer) and by value
25
+ * Javascript functions can be used as C callbacks (since 1.2.0)
26
+ * Well-tested code base for popular OS/architecture combinations
28
27
 
29
28
  The following combinations of OS and architectures __are officially supported and tested__ at the moment:
30
29
 
@@ -41,7 +40,10 @@ RISC-V 64 [^4] | ⬜️ *N/A* | 🟩 Yes | ⬜️ *N/A* | 🟨 Proba
41
40
  [^3]: However, we don't provide prebuilt binaries for macOS on Apple M1.
42
41
  [^4]: Only the LP64D (double-precision float) ABI gets tested. The LP64 ABI is supported in theory (untested), the LP64F ABI is not supported.
43
42
 
44
- This is still in development, bugs are to be expected. More tests will come in the near future.
43
+ The following features are planned in the near future:
44
+
45
+ * 1.3: Real-world examples, optimize passing of structs and arrays
46
+ * 1.4: Type parser, unions
45
47
 
46
48
  # Get started
47
49
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koffi",
3
- "version": "1.2.0-alpha.3",
3
+ "version": "1.2.0-alpha.4",
4
4
  "description": "Fast and simple C FFI (foreign function interface) for Node.js",
5
5
  "keywords": [
6
6
  "foreign",
@@ -41,12 +41,14 @@
41
41
  "benchmark/raylib_*",
42
42
  "qemu/qemu.js",
43
43
  "qemu/registry",
44
+ "test/async.js",
45
+ "test/callbacks.js",
44
46
  "test/CMakeLists.txt",
45
47
  "test/misc.c",
46
48
  "test/misc.def",
47
- "test/misc.js",
48
49
  "test/raylib.js",
49
50
  "test/sqlite.js",
51
+ "test/sync.js",
50
52
  "vendor",
51
53
  "LICENSE.txt",
52
54
  "README.md",
@@ -37,9 +37,9 @@
37
37
  "commands": {
38
38
  "Test Sync": "node test/sync.js",
39
39
  "Test Async": "node test/async.js",
40
+ "Test Callbacks": "node test/callbacks.js",
40
41
  "Test Raylib": "xvfb-run node test/raylib.js",
41
- "Test SQLite": "node test/sqlite.js",
42
- "Test Callbacks": "node test/callbacks.js"
42
+ "Test SQLite": "node test/sqlite.js"
43
43
  }
44
44
  }
45
45
  }
@@ -83,9 +83,9 @@
83
83
  "commands": {
84
84
  "Test Sync": "node test/sync.js",
85
85
  "Test Async": "node test/async.js",
86
+ "Test Callbacks": "node test/callbacks.js",
86
87
  "Test Raylib": "xvfb-run node test/raylib.js",
87
- "Test SQLite": "node test/sqlite.js",
88
- "Test Callbacks": "node test/callbacks.js"
88
+ "Test SQLite": "node test/sqlite.js"
89
89
  }
90
90
  }
91
91
  }
@@ -129,9 +129,9 @@
129
129
  "commands": {
130
130
  "Test Sync": "node test/sync.js",
131
131
  "Test Async": "node test/async.js",
132
+ "Test Callbacks": "node test/callbacks.js",
132
133
  "Test Raylib": "xvfb-run node test/raylib.js",
133
- "Test SQLite": "node test/sqlite.js",
134
- "Test Callbacks": "node test/callbacks.js"
134
+ "Test SQLite": "node test/sqlite.js"
135
135
  }
136
136
  }
137
137
  }
@@ -175,9 +175,9 @@
175
175
  "commands": {
176
176
  "Test Sync": "node test/sync.js",
177
177
  "Test Async": "node test/async.js",
178
+ "Test Callbacks": "node test/callbacks.js",
178
179
  "Test Raylib": "xvfb-run node test/raylib.js",
179
- "Test SQLite": "node test/sqlite.js",
180
- "Test Callbacks": "node test/callbacks.js"
180
+ "Test SQLite": "node test/sqlite.js"
181
181
  }
182
182
  }
183
183
  }
@@ -228,9 +228,9 @@
228
228
  "commands": {
229
229
  "Test Sync": "C:\\Node32\\node32.cmd node test/sync.js",
230
230
  "Test Async": "C:\\Node32\\node32.cmd node test/async.js",
231
+ "Test Callbacks": "C:\\Node32\\node32.cmd node test/callbacks.js",
231
232
  "Test Raylib": "seatsh C:\\Node32\\node32.cmd node test/raylib.js",
232
- "Test SQLite": "C:\\Node32\\node32.cmd node test/sqlite.js",
233
- "Test Callbacks": "C:\\Node32\\node32.cmd node test/callbacks.js"
233
+ "Test SQLite": "C:\\Node32\\node32.cmd node test/sqlite.js"
234
234
  }
235
235
  },
236
236
 
@@ -242,9 +242,9 @@
242
242
  "commands": {
243
243
  "Test Sync": "C:\\Node64\\node64.cmd node test/sync.js",
244
244
  "Test Async": "C:\\Node64\\node64.cmd node test/async.js",
245
+ "Test Callbacks": "C:\\Node64\\node64.cmd node test/callbacks.js",
245
246
  "Test Raylib": "seatsh C:\\Node64\\node64.cmd node test/raylib.js",
246
- "Test SQLite": "C:\\Node64\\node64.cmd node test/sqlite.js",
247
- "Test Callbacks": "C:\\Node64\\node64.cmd node test/callbacks.js"
247
+ "Test SQLite": "C:\\Node64\\node64.cmd node test/sqlite.js"
248
248
  }
249
249
  }
250
250
  }
@@ -288,9 +288,9 @@
288
288
  "commands": {
289
289
  "Test Sync": "node test/sync.js",
290
290
  "Test Async": "node test/async.js",
291
+ "Test Callbacks": "node test/callbacks.js",
291
292
  "Test Raylib": "xvfb-run node test/raylib.js",
292
- "Test SQLite": "node test/sqlite.js",
293
- "Test Callbacks": "node test/callbacks.js"
293
+ "Test SQLite": "node test/sqlite.js"
294
294
  }
295
295
  }
296
296
  }
@@ -334,9 +334,9 @@
334
334
  "commands": {
335
335
  "Test Sync": "node test/sync.js",
336
336
  "Test Async": "node test/async.js",
337
+ "Test Callbacks": "node test/callbacks.js",
337
338
  "Test Raylib": "xvfb-run node test/raylib.js",
338
- "Test SQLite": "node test/sqlite.js",
339
- "Test Callbacks": "node test/callbacks.js"
339
+ "Test SQLite": "node test/sqlite.js"
340
340
  }
341
341
  }
342
342
  }
@@ -380,9 +380,9 @@
380
380
  "commands": {
381
381
  "Test Sync": "node test/sync.js",
382
382
  "Test Async": "node test/async.js",
383
+ "Test Callbacks": "node test/callbacks.js",
383
384
  "Test Raylib": "xvfb-run node test/raylib.js",
384
- "Test SQLite": "node test/sqlite.js",
385
- "Test Callbacks": "node test/callbacks.js"
385
+ "Test SQLite": "node test/sqlite.js"
386
386
  }
387
387
  }
388
388
  }
@@ -426,8 +426,8 @@
426
426
  "commands": {
427
427
  "Test Sync": "PATH=/usr/local/bin:/usr/bin:/bin node test/sync.js",
428
428
  "Test Async": "PATH=/usr/local/bin:/usr/bin:/bin node test/async.js",
429
- "Test SQLite": "PATH=/usr/local/bin:/usr/bin:/bin node test/sqlite.js",
430
- "Test Callbacks": "PATH=/usr/local/bin:/usr/bin:/bin node test/callbacks.js"
429
+ "Test Callbacks": "PATH=/usr/local/bin:/usr/bin:/bin node test/callbacks.js",
430
+ "Test SQLite": "PATH=/usr/local/bin:/usr/bin:/bin node test/sqlite.js"
431
431
  }
432
432
  }
433
433
  }
@@ -471,9 +471,9 @@
471
471
  "commands": {
472
472
  "Test Sync": "node test/sync.js",
473
473
  "Test Async": "node test/async.js",
474
+ "Test Callbacks": "node test/callbacks.js",
474
475
  "Test Raylib": "xvfb-run node test/raylib.js",
475
- "Test SQLite": "node test/sqlite.js",
476
- "Test Callbacks": "node test/callbacks.js"
476
+ "Test SQLite": "node test/sqlite.js"
477
477
  }
478
478
  }
479
479
  }
@@ -517,9 +517,9 @@
517
517
  "commands": {
518
518
  "Test Sync": "node test/sync.js",
519
519
  "Test Async": "node test/async.js",
520
+ "Test Callbacks": "node test/callbacks.js",
520
521
  "Test Raylib": "xvfb-run node test/raylib.js",
521
- "Test SQLite": "node test/sqlite.js",
522
- "Test Callbacks": "node test/callbacks.js"
522
+ "Test SQLite": "node test/sqlite.js"
523
523
  }
524
524
  }
525
525
  }
@@ -563,9 +563,9 @@
563
563
  "commands": {
564
564
  "Test Sync": "node test/sync.js",
565
565
  "Test Async": "node test/async.js",
566
+ "Test Callbacks": "node test/callbacks.js",
566
567
  "Test Raylib": "xvfb-run node test/raylib.js",
567
- "Test SQLite": "node test/sqlite.js",
568
- "Test Callbacks": "node test/callbacks.js"
568
+ "Test SQLite": "node test/sqlite.js"
569
569
  }
570
570
  }
571
571
  }
package/src/abi_arm32.cc CHANGED
@@ -139,10 +139,11 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
139
139
  } break;
140
140
  case PrimitiveKind::Int64:
141
141
  case PrimitiveKind::UInt64: {
142
- int need = 2 + (gpr_avail % 2);
142
+ bool realign = gpr_avail % 2;
143
+ int need = 2 + realign;
143
144
 
144
145
  if (gpr_avail >= need) {
145
- param.gpr_count = need;
146
+ param.gpr_count = 2;
146
147
  gpr_avail -= need;
147
148
  } else {
148
149
  started_stack = true;
@@ -160,13 +161,14 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
160
161
  started_stack = true;
161
162
  }
162
163
  } else {
163
- int gpr_count = (param.type->size + 3) / 4;
164
+ bool realign = (param.type->align == 8 && (gpr_avail % 2));
165
+ int need = (param.type->size + 3) / 4 + realign;
164
166
 
165
- if (gpr_count <= gpr_avail) {
166
- param.gpr_count = gpr_count;
167
- gpr_avail -= gpr_count;
167
+ if (need <= gpr_avail) {
168
+ param.gpr_count = need - realign;
169
+ gpr_avail -= need;
168
170
  } else if (!started_stack) {
169
- param.gpr_count = gpr_avail;
171
+ param.gpr_count = gpr_avail - realign;
170
172
  gpr_avail = 0;
171
173
 
172
174
  started_stack = true;
@@ -195,7 +197,7 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
195
197
  need += (gpr_avail % 2);
196
198
 
197
199
  if (need <= gpr_avail) {
198
- param.gpr_count = need;
200
+ param.gpr_count = 2;
199
201
  gpr_avail -= need;
200
202
  } else {
201
203
  started_stack = true;
@@ -214,7 +216,7 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
214
216
 
215
217
  bool CallData::Prepare(const Napi::CallbackInfo &info)
216
218
  {
217
- uint8_t *args_ptr = nullptr;
219
+ uint32_t *args_ptr = nullptr;
218
220
  uint32_t *gpr_ptr = nullptr;
219
221
  uint32_t *vec_ptr = nullptr;
220
222
 
@@ -251,13 +253,7 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
251
253
  }
252
254
 
253
255
  bool b = value.As<Napi::Boolean>();
254
-
255
- if (RG_LIKELY(param.gpr_count)) {
256
- *(gpr_ptr++) = (uint32_t)b;
257
- } else {
258
- *args_ptr = (uint8_t)b;
259
- args_ptr += 4;
260
- }
256
+ *((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint32_t)b;
261
257
  } break;
262
258
  case PrimitiveKind::Int8:
263
259
  case PrimitiveKind::UInt8:
@@ -270,13 +266,7 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
270
266
  }
271
267
 
272
268
  int32_t v = CopyNumber<int32_t>(value);
273
-
274
- if (RG_LIKELY(param.gpr_count)) {
275
- *(int32_t *)(gpr_ptr++) = v;
276
- } else {
277
- *(int32_t *)args_ptr = v;
278
- args_ptr += 4;
279
- }
269
+ *(int32_t *)((param.gpr_count ? gpr_ptr : args_ptr)++) = v;
280
270
  } break;
281
271
  case PrimitiveKind::UInt32: {
282
272
  if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
@@ -285,13 +275,7 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
285
275
  }
286
276
 
287
277
  uint32_t v = CopyNumber<uint32_t>(value);
288
-
289
- if (RG_LIKELY(param.gpr_count)) {
290
- *(gpr_ptr++) = v;
291
- } else {
292
- *(uint32_t *)args_ptr = v;
293
- args_ptr += 4;
294
- }
278
+ *((param.gpr_count ? gpr_ptr : args_ptr)++) = v;
295
279
  } break;
296
280
  case PrimitiveKind::Int64: {
297
281
  if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
@@ -302,13 +286,13 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
302
286
  int64_t v = CopyNumber<int64_t>(value);
303
287
 
304
288
  if (RG_LIKELY(param.gpr_count)) {
305
- gpr_ptr += param.gpr_count - 2;
289
+ gpr_ptr = AlignUp(gpr_ptr, 8);
306
290
  *(int64_t *)gpr_ptr = v;
307
291
  gpr_ptr += param.gpr_count;
308
292
  } else {
309
293
  args_ptr = AlignUp(args_ptr, 8);
310
294
  *(int64_t *)args_ptr = v;
311
- args_ptr += 8;
295
+ args_ptr += 2;
312
296
  }
313
297
  } break;
314
298
  case PrimitiveKind::UInt64: {
@@ -320,13 +304,13 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
320
304
  uint64_t v = CopyNumber<uint64_t>(value);
321
305
 
322
306
  if (RG_LIKELY(param.gpr_count)) {
323
- gpr_ptr += param.gpr_count - 2;
307
+ gpr_ptr = AlignUp(gpr_ptr, 8);
324
308
  *(uint64_t *)gpr_ptr = v;
325
309
  gpr_ptr += param.gpr_count;
326
310
  } else {
327
311
  args_ptr = AlignUp(args_ptr, 8);
328
312
  *(uint64_t *)args_ptr = v;
329
- args_ptr += 8;
313
+ args_ptr += 2;
330
314
  }
331
315
  } break;
332
316
  case PrimitiveKind::String: {
@@ -342,12 +326,7 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
342
326
  return false;
343
327
  }
344
328
 
345
- if (RG_LIKELY(param.gpr_count)) {
346
- *(gpr_ptr++) = (uint64_t)str;
347
- } else {
348
- *(const char **)args_ptr = str;
349
- args_ptr += 4;
350
- }
329
+ *(const char **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str;
351
330
  } break;
352
331
  case PrimitiveKind::String16: {
353
332
  const char16_t *str16;
@@ -362,12 +341,7 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
362
341
  return false;
363
342
  }
364
343
 
365
- if (RG_LIKELY(param.gpr_count)) {
366
- *(gpr_ptr++) = (uint64_t)str16;
367
- } else {
368
- *(const char16_t **)args_ptr = str16;
369
- args_ptr += 4;
370
- }
344
+ *(const char16_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str16;
371
345
  } break;
372
346
  case PrimitiveKind::Pointer: {
373
347
  uint8_t *ptr;
@@ -400,12 +374,7 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
400
374
  return false;
401
375
  }
402
376
 
403
- if (RG_LIKELY(param.gpr_count)) {
404
- *(gpr_ptr++) = (uint64_t)ptr;
405
- } else {
406
- *(void **)args_ptr = ptr;
407
- args_ptr += 4;
408
- }
377
+ *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
409
378
  } break;
410
379
  case PrimitiveKind::Record: {
411
380
  if (RG_UNLIKELY(!IsObject(value))) {
@@ -422,18 +391,21 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
422
391
  } else if (param.gpr_count) {
423
392
  RG_ASSERT(param.type->align <= 8);
424
393
 
394
+ int16_t align = (param.type->align <= 4) ? 4 : 8;
395
+ gpr_ptr = AlignUp(gpr_ptr, align);
396
+
425
397
  if (!PushObject(obj, param.type, (uint8_t *)gpr_ptr))
426
398
  return false;
427
399
 
428
400
  gpr_ptr += param.gpr_count;
429
- args_ptr += AlignLen(param.type->size - param.gpr_count * 4, 4);
401
+ args_ptr += (param.type->size - param.gpr_count * 4 + 3) / 4;
430
402
  } else if (param.type->size) {
431
403
  int16_t align = (param.type->align <= 4) ? 4 : 8;
432
-
433
404
  args_ptr = AlignUp(args_ptr, align);
434
- if (!PushObject(obj, param.type, args_ptr))
405
+
406
+ if (!PushObject(obj, param.type, (uint8_t *)args_ptr))
435
407
  return false;
436
- args_ptr += AlignLen(param.type->size, 4);
408
+ args_ptr += (param.type->size + 3) / 4;
437
409
  }
438
410
  } break;
439
411
  case PrimitiveKind::Array: { RG_UNREACHABLE(); } break;
@@ -450,8 +422,7 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
450
422
  } else if (param.gpr_count) {
451
423
  *(float *)(gpr_ptr++) = f;
452
424
  } else {
453
- *(float *)args_ptr = f;
454
- args_ptr += 4;
425
+ *(float *)(args_ptr++) = f;
455
426
  }
456
427
  } break;
457
428
  case PrimitiveKind::Float64: {
@@ -466,13 +437,13 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
466
437
  *(double *)vec_ptr = d;
467
438
  vec_ptr += 2;
468
439
  } else if (param.gpr_count) {
469
- gpr_ptr += (param.gpr_count - 2);
440
+ gpr_ptr = AlignUp(gpr_ptr, 8);
470
441
  *(double *)gpr_ptr = d;
471
442
  gpr_ptr += 2;
472
443
  } else {
473
444
  args_ptr = AlignUp(args_ptr, 8);
474
445
  *(double *)args_ptr = d;
475
- args_ptr += 8;
446
+ args_ptr += 2;
476
447
  }
477
448
  } break;
478
449
  case PrimitiveKind::Callback: {
@@ -495,12 +466,7 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
495
466
  return false;
496
467
  }
497
468
 
498
- if (RG_LIKELY(param.gpr_count)) {
499
- *(gpr_ptr++) = (uint32_t)ptr;
500
- } else {
501
- *(void **)args_ptr = ptr;
502
- args_ptr += 4;
503
- }
469
+ *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
504
470
  } break;
505
471
  }
506
472
  }
@@ -668,7 +634,8 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegister
668
634
  arguments.Append(arg);
669
635
  } break;
670
636
  case PrimitiveKind::Int64: {
671
- gpr_ptr += param.gpr_count - 2;
637
+ gpr_ptr = AlignUp(gpr_ptr, 8);
638
+
672
639
  int64_t v = *(int64_t *)(param.gpr_count ? gpr_ptr : args_ptr);
673
640
  (param.gpr_count ? gpr_ptr : args_ptr) += 2;
674
641
 
@@ -676,7 +643,8 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegister
676
643
  arguments.Append(arg);
677
644
  } break;
678
645
  case PrimitiveKind::UInt64: {
679
- gpr_ptr += param.gpr_count - 2;
646
+ gpr_ptr = AlignUp(gpr_ptr, 8);
647
+
680
648
  uint64_t v = *(uint64_t *)(param.gpr_count ? gpr_ptr : args_ptr);
681
649
  (param.gpr_count ? gpr_ptr : args_ptr) += 2;
682
650
 
@@ -717,11 +685,32 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegister
717
685
  } else if (param.gpr_count) {
718
686
  RG_ASSERT(param.type->align <= 8);
719
687
 
720
- Napi::Object obj = PopObject((const uint8_t *)gpr_ptr, param.type);
721
- arguments.Append(obj);
688
+ int16_t gpr_size = param.gpr_count * 4;
689
+ int16_t align = (param.type->align <= 4) ? 4 : 8;
690
+ gpr_ptr = AlignUp(gpr_ptr, align);
722
691
 
723
- gpr_ptr += param.gpr_count;
724
- args_ptr += (param.type->size - param.gpr_count * 4 + 3) / 4;
692
+ if (param.type->size > gpr_size) {
693
+ uint8_t *ptr;
694
+
695
+ // XXX: Expensive, and error can't be managed by calling C code.
696
+ // But the object is split between the GPRs and the caller stack.
697
+ if (RG_UNLIKELY(!AllocHeap(param.type->size, 16, &ptr)))
698
+ return;
699
+
700
+ memcpy(ptr, gpr_ptr, gpr_size);
701
+ memcpy(ptr + gpr_size, args_ptr, param.type->size - gpr_size);
702
+
703
+ Napi::Object obj = PopObject(ptr, param.type);
704
+ arguments.Append(obj);
705
+
706
+ gpr_ptr += param.gpr_count;
707
+ args_ptr += (param.type->size - gpr_size + 3) / 4;
708
+ } else {
709
+ Napi::Object obj = PopObject((const uint8_t *)gpr_ptr, param.type);
710
+ arguments.Append(obj);
711
+
712
+ gpr_ptr += param.gpr_count;
713
+ }
725
714
  } else if (param.type->size) {
726
715
  int16_t align = (param.type->align <= 4) ? 4 : 8;
727
716
  args_ptr = AlignUp(args_ptr, align);
@@ -752,10 +741,11 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegister
752
741
  d = *(double *)vec_ptr;
753
742
  vec_ptr += 2;
754
743
  } else if (param.gpr_count) {
755
- gpr_ptr += param.gpr_count - 2;
744
+ gpr_ptr = AlignUp(gpr_ptr, 8);
756
745
  d = *(double *)gpr_ptr;
757
746
  gpr_ptr += 2;
758
747
  } else {
748
+ args_ptr = AlignUp(args_ptr, 8);
759
749
  d = *(double *)args_ptr;
760
750
  args_ptr += 2;
761
751
  }
@@ -290,8 +290,8 @@ TrampolineX15:
290
290
  trampoline_vec 15
291
291
 
292
292
  # When a callback is relayed, Koffi will call into Node.js and V8 to execute Javascript.
293
- # The propblem is that we're still running on the separate Koffi stack, and V8 will
294
- # preobably misdetect this as a "stack overflow". We have to restore the old
293
+ # The problem is that we're still running on the separate Koffi stack, and V8 will
294
+ # probably misdetect this as a "stack overflow". We have to restore the old
295
295
  # stack pointer, call Node.js/V8 and go back to ours.
296
296
  # The first three parameters (r0, r1, r2) are passed through untouched.
297
297
  CallSwitchStack: