ffi 1.13.1 → 1.14.0

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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/README.md +10 -2
  4. data/ext/ffi_c/AbstractMemory.c +25 -26
  5. data/ext/ffi_c/Buffer.c +2 -7
  6. data/ext/ffi_c/Call.c +2 -7
  7. data/ext/ffi_c/ClosurePool.c +64 -11
  8. data/ext/ffi_c/ClosurePool.h +3 -1
  9. data/ext/ffi_c/DynamicLibrary.c +1 -6
  10. data/ext/ffi_c/Function.c +8 -13
  11. data/ext/ffi_c/FunctionInfo.c +2 -6
  12. data/ext/ffi_c/LastError.c +2 -6
  13. data/ext/ffi_c/MemoryPointer.c +2 -7
  14. data/ext/ffi_c/MethodHandle.c +4 -8
  15. data/ext/ffi_c/Platform.c +2 -7
  16. data/ext/ffi_c/Pointer.c +24 -25
  17. data/ext/ffi_c/Struct.c +3 -6
  18. data/ext/ffi_c/StructByValue.c +2 -7
  19. data/ext/ffi_c/StructLayout.c +2 -5
  20. data/ext/ffi_c/Thread.c +0 -5
  21. data/ext/ffi_c/Thread.h +1 -6
  22. data/ext/ffi_c/Type.c +1 -1
  23. data/ext/ffi_c/Variadic.c +2 -7
  24. data/ext/ffi_c/extconf.rb +17 -4
  25. data/ext/ffi_c/libffi/.travis/bfin-sim.exp +1 -1
  26. data/ext/ffi_c/libffi/.travis/m32r-sim.exp +1 -1
  27. data/ext/ffi_c/libffi/.travis/moxie-sim.exp +1 -1
  28. data/ext/ffi_c/libffi/.travis/or1k-sim.exp +1 -1
  29. data/ext/ffi_c/libffi/.travis/powerpc-eabisim.exp +1 -1
  30. data/ext/ffi_c/libffi/.travis/wine-sim.exp +1 -1
  31. data/ext/ffi_c/libffi/Makefile.am +48 -58
  32. data/ext/ffi_c/libffi/README.md +4 -0
  33. data/ext/ffi_c/libffi/config.guess +552 -331
  34. data/ext/ffi_c/libffi/config.sub +1321 -1306
  35. data/ext/ffi_c/libffi/configure.ac +6 -1
  36. data/ext/ffi_c/libffi/configure.host +32 -20
  37. data/ext/ffi_c/libffi/doc/Makefile.am +3 -0
  38. data/ext/ffi_c/libffi/doc/libffi.texi +997 -0
  39. data/ext/ffi_c/libffi/doc/version.texi +4 -0
  40. data/ext/ffi_c/libffi/generate-darwin-source-and-headers.py +1 -1
  41. data/ext/ffi_c/libffi/msvcc.sh +11 -11
  42. data/ext/ffi_c/libffi/src/aarch64/ffi.c +45 -35
  43. data/ext/ffi_c/libffi/src/aarch64/ffitarget.h +10 -5
  44. data/ext/ffi_c/libffi/src/aarch64/internal.h +1 -0
  45. data/ext/ffi_c/libffi/src/aarch64/sysv.S +1 -1
  46. data/ext/ffi_c/libffi/src/aarch64/win64_armasm.S +1 -1
  47. data/ext/ffi_c/libffi/src/arm/ffi.c +22 -0
  48. data/ext/ffi_c/libffi/src/arm/sysv.S +4 -4
  49. data/ext/ffi_c/libffi/src/closures.c +23 -6
  50. data/ext/ffi_c/libffi/src/csky/ffi.c +395 -0
  51. data/ext/ffi_c/libffi/src/csky/ffitarget.h +63 -0
  52. data/ext/ffi_c/libffi/src/csky/sysv.S +371 -0
  53. data/ext/ffi_c/libffi/src/dlmalloc.c +1 -1
  54. data/ext/ffi_c/libffi/src/kvx/asm.h +5 -0
  55. data/ext/ffi_c/libffi/src/kvx/ffi.c +273 -0
  56. data/ext/ffi_c/libffi/src/kvx/ffitarget.h +75 -0
  57. data/ext/ffi_c/libffi/src/kvx/sysv.S +127 -0
  58. data/ext/ffi_c/libffi/src/mips/ffi.c +5 -1
  59. data/ext/ffi_c/libffi/src/mips/ffitarget.h +1 -1
  60. data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +13 -1
  61. data/ext/ffi_c/libffi/src/powerpc/ffi_powerpc.h +1 -1
  62. data/ext/ffi_c/libffi/src/powerpc/linux64.S +8 -0
  63. data/ext/ffi_c/libffi/src/powerpc/linux64_closure.S +13 -1
  64. data/ext/ffi_c/libffi/src/prep_cif.c +1 -1
  65. data/ext/ffi_c/libffi/src/x86/ffi.c +8 -2
  66. data/ext/ffi_c/libffi/src/x86/ffi64.c +7 -0
  67. data/ext/ffi_c/libffi/src/x86/ffiw64.c +5 -0
  68. data/ext/ffi_c/libffi/src/x86/sysv.S +2 -2
  69. data/ext/ffi_c/libffi/src/x86/unix64.S +1 -2
  70. data/ext/ffi_c/libffi/src/x86/win64.S +3 -2
  71. data/ext/ffi_c/libffi/src/x86/win64_intel.S +3 -2
  72. data/ext/ffi_c/libffi/testsuite/lib/libffi.exp +22 -2
  73. data/ext/ffi_c/libffi/testsuite/libffi.bhaible/test-call.c +4 -4
  74. data/ext/ffi_c/libffi/testsuite/libffi.bhaible/test-callback.c +2 -2
  75. data/ext/ffi_c/libffi/testsuite/libffi.closures/huge_struct.c +2 -0
  76. data/ffi.gemspec +1 -1
  77. data/lib/ffi.rb +2 -2
  78. data/lib/ffi/abstract_memory.rb +44 -0
  79. data/lib/ffi/ffi.rb +1 -0
  80. data/lib/ffi/library.rb +1 -1
  81. data/lib/ffi/platform.rb +15 -6
  82. data/lib/ffi/platform/aarch64-darwin/types.conf +130 -0
  83. data/lib/ffi/platform/aarch64-openbsd/types.conf +134 -0
  84. data/lib/ffi/platform/x86_64-haiku/types.conf +117 -0
  85. data/lib/ffi/platform/x86_64-msys/types.conf +119 -0
  86. data/lib/ffi/pointer.rb +21 -7
  87. data/lib/ffi/version.rb +1 -1
  88. metadata +15 -11
  89. data/.appveyor.yml +0 -30
  90. data/.github/workflows/ci.yml +0 -64
  91. data/.gitignore +0 -25
  92. data/.gitmodules +0 -4
  93. data/.travis.yml +0 -58
  94. data/.yardopts +0 -5
  95. data/ext/ffi_c/win32/stdbool.h +0 -8
  96. data/ext/ffi_c/win32/stdint.h +0 -201
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7c1ae7c590f7dd4d8d821c6faf31c66499a90c421ff25fe14ce4465cc058b83f
4
- data.tar.gz: e4c16035d46e13e752e215fdc87511c214db31cec9084cca3c2141a9d83469c7
3
+ metadata.gz: 2c0a1872f48b6db1c64ae5390e0e76455fa27ae7016e5a0426753e4973b53751
4
+ data.tar.gz: 2e9a65f7e151185182a42848eebbd0709fee683d3513e096c7552a669a5326a6
5
5
  SHA512:
6
- metadata.gz: a4064371f99217b7b449c46915e4505b54a61785ec27a2b5cd51d798cc929ff58bef33ad9064ab93ca85ad2c5d5c07d515edb0ac5d673a468fb17abf18565627
7
- data.tar.gz: a545c796f0b36fb7cac6ac06a73094274d077e0e0f54f55f67c129e6bff27b7679886a3adc87e9b3c173f975864dc78ac3d6277d8a8d1352f974b697ace0f8b4
6
+ metadata.gz: 9c78c1d0e46f1bcc9e0ff29dafadb660970ff86f54fb5326dc63e81eecee307e9e22e187c07dc2f9982ffff7c3a3c913caaeb2136683f5990466d452b87ec23c
7
+ data.tar.gz: a5c06fa33eb31dd59f26ee10796609bfee821d076107e5f6ac2ab131f39fbb4979d00f84d98e1e556268ee55f310f8bbda1c770d0af5b98d72b314c1fdd9b0a1
@@ -1,3 +1,28 @@
1
+ 1.14.0 / 2020-12-18
2
+ -------------------
3
+
4
+ Added:
5
+ * Add types.conf for x86_64-msys, x86_64-haiku, aarch64-openbsd and aarch64-darwin (alias arm64-darwin)
6
+ * Add method AbstractMemory#size_limit? . #829
7
+ * Add new extconf option --enable-libffi-alloc which is enabled per default on Apple M1 (arm64-darwin).
8
+
9
+ Changed:
10
+ * Do NULL pointer check only when array length > 0 . #305
11
+ * Raise an error on an unknown order argument. #830
12
+ * Change FFI::Pointer#write_string to terminate with a NUL byte like other string methods. #805
13
+ * Update bundled libffi to latest master.
14
+
15
+ Removed:
16
+ * Remove win32/stdint.h and stdbool.h because of copyright issue. #693
17
+
18
+ Fixed:
19
+ * Fix possible UTF-8 load error in loader script interpretation. #792
20
+ * Fix segfault on non-array argument to #write_array_of_*
21
+ * Fix memory leak in MethodHandle . #815
22
+ * Fix possible segfault in combination with fiddle or other libffi using gems . #835
23
+ * Fix possibility to use ffi ruby gem with JRuby-9.3 . #763
24
+
25
+
1
26
  1.13.1 / 2020-06-09
2
27
  -------------------
3
28
 
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Ruby-FFI https://github.com/ffi/ffi/wiki [![Build Status](https://travis-ci.org/ffi/ffi.svg?branch=master)](https://travis-ci.org/ffi/ffi) [![Build status Windows](https://ci.appveyor.com/api/projects/status/r8wxn1sd4s794gg1/branch/master?svg=true)](https://ci.appveyor.com/project/larskanis/ffi-aofqa/branch/master)
1
+ # Ruby-FFI https://github.com/ffi/ffi/wiki [![Build Status](https://travis-ci.com/ffi/ffi.svg?branch=master)](https://travis-ci.com/ffi/ffi) [![Build status Windows](https://ci.appveyor.com/api/projects/status/r8wxn1sd4s794gg1/branch/master?svg=true)](https://ci.appveyor.com/project/larskanis/ffi-aofqa/branch/master)
2
2
 
3
3
  ## Description
4
4
 
@@ -66,10 +66,18 @@ From rubygems:
66
66
  or from the git repository on github:
67
67
 
68
68
  git clone git://github.com/ffi/ffi.git
69
- git submodule update --init --recursive
70
69
  cd ffi
70
+ git submodule update --init --recursive
71
+ bundle install
71
72
  rake install
72
73
 
74
+ ### Install options:
75
+
76
+ * `--enable-system-libffi` : Force usage of system libffi
77
+ * `--disable-system-libffi` : Force usage of builtin libffi
78
+ * `--enable-libffi-alloc` : Force closure allocation by libffi
79
+ * `--disable-libffi-alloc` : Force closure allocation by builtin method
80
+
73
81
  ## License
74
82
 
75
83
  The ffi library is covered by the BSD license, also see the LICENSE file.
@@ -32,12 +32,9 @@
32
32
  #include <sys/types.h>
33
33
  #ifndef _MSC_VER
34
34
  # include <sys/param.h>
35
- # include <stdint.h>
36
- # include <stdbool.h>
37
- #else
38
- # include "win32/stdbool.h"
39
- # include "win32/stdint.h"
40
35
  #endif
36
+ #include <stdint.h>
37
+ #include <stdbool.h>
41
38
 
42
39
  #include <limits.h>
43
40
  #include <ruby.h>
@@ -135,11 +132,13 @@ static VALUE memory_put_array_of_##name(VALUE self, VALUE offset, VALUE ary); \
135
132
  static VALUE \
136
133
  memory_put_array_of_##name(VALUE self, VALUE offset, VALUE ary) \
137
134
  { \
138
- long count = RARRAY_LEN(ary); \
135
+ long count; \
139
136
  long off = NUM2LONG(offset); \
140
137
  AbstractMemory* memory = MEMORY(self); \
141
138
  long i; \
142
- checkWrite(memory); \
139
+ Check_Type(ary, T_ARRAY); \
140
+ count = RARRAY_LEN(ary); \
141
+ if (likely(count > 0)) checkWrite(memory); \
143
142
  checkBounds(memory, off, count * sizeof(type)); \
144
143
  for (i = 0; i < count; i++) { \
145
144
  type tmp = (type) VAL(toNative(RARRAY_PTR(ary)[i]), swap); \
@@ -162,7 +161,7 @@ memory_get_array_of_##name(VALUE self, VALUE offset, VALUE length) \
162
161
  AbstractMemory* memory = MEMORY(self); \
163
162
  VALUE retVal = rb_ary_new2(count); \
164
163
  long i; \
165
- checkRead(memory); \
164
+ if (likely(count > 0)) checkRead(memory); \
166
165
  checkBounds(memory, off, count * sizeof(type)); \
167
166
  for (i = 0; i < count; ++i) { \
168
167
  type tmp; \
@@ -209,13 +208,13 @@ SWAPU16(uint16_t x)
209
208
  ((x >> 40) & 0x000000000000ff00ULL) | \
210
209
  ((x >> 56) & 0x00000000000000ffULL))
211
210
 
212
- static inline int32_t
211
+ static inline int32_t
213
212
  SWAPS32(int32_t x)
214
213
  {
215
214
  return bswap32(x);
216
215
  }
217
216
 
218
- static inline uint32_t
217
+ static inline uint32_t
219
218
  SWAPU32(uint32_t x)
220
219
  {
221
220
  return bswap32(x);
@@ -450,7 +449,7 @@ memory_get_array_of_string(int argc, VALUE* argv, VALUE self)
450
449
  int i;
451
450
 
452
451
  checkBounds(ptr, off, count * sizeof (char*));
453
-
452
+
454
453
  for (i = 0; i < count; ++i) {
455
454
  const char* strptr = *((const char**) (ptr->address + off) + i);
456
455
  rb_ary_push(retVal, (strptr == NULL ? Qnil : rb_str_new2(strptr)));
@@ -477,7 +476,7 @@ memory_get_array_of_string(int argc, VALUE* argv, VALUE self)
477
476
  * @param [Numeric] count number of strings to get. If nil, return all strings
478
477
  * @return [Array<String>]
479
478
  */
480
- static VALUE
479
+ static VALUE
481
480
  memory_read_array_of_string(int argc, VALUE* argv, VALUE self)
482
481
  {
483
482
  VALUE* rargv = ALLOCA_N(VALUE, argc + 1);
@@ -500,7 +499,7 @@ memory_read_array_of_string(int argc, VALUE* argv, VALUE self)
500
499
  * @raise {SecurityError} when writing unsafe string to memory
501
500
  * @raise {IndexError} if +offset+ is too great
502
501
  * @raise {NullPointerError} if memory not initialized
503
- * Put a string in memory.
502
+ * Put a string in memory. Writes a final \0 byte.
504
503
  */
505
504
  static VALUE
506
505
  memory_put_string(VALUE self, VALUE offset, VALUE str)
@@ -535,13 +534,13 @@ memory_get_bytes(VALUE self, VALUE offset, VALUE length)
535
534
  {
536
535
  AbstractMemory* ptr = MEMORY(self);
537
536
  long off, len;
538
-
537
+
539
538
  off = NUM2LONG(offset);
540
539
  len = NUM2LONG(length);
541
540
 
542
541
  checkRead(ptr);
543
542
  checkBounds(ptr, off, len);
544
-
543
+
545
544
  return rb_str_new((char *) ptr->address + off, len);
546
545
  }
547
546
 
@@ -595,7 +594,7 @@ memory_put_bytes(int argc, VALUE* argv, VALUE self)
595
594
  * equivalent to :
596
595
  * memory.get_bytes(0, length)
597
596
  */
598
- static VALUE
597
+ static VALUE
599
598
  memory_read_bytes(VALUE self, VALUE length)
600
599
  {
601
600
  return memory_get_bytes(self, INT2FIX(0), length);
@@ -610,7 +609,7 @@ memory_read_bytes(VALUE self, VALUE length)
610
609
  * equivalent to :
611
610
  * memory.put_bytes(0, str, index, length)
612
611
  */
613
- static VALUE
612
+ static VALUE
614
613
  memory_write_bytes(int argc, VALUE* argv, VALUE self)
615
614
  {
616
615
  VALUE* wargv = ALLOCA_N(VALUE, argc + 1);
@@ -643,7 +642,7 @@ memory_type_size(VALUE self)
643
642
  * Document-method: []
644
643
  * call-seq: memory[idx]
645
644
  * @param [Numeric] idx index to access in memory
646
- * @return
645
+ * @return
647
646
  * Memory read accessor.
648
647
  */
649
648
  static VALUE
@@ -748,9 +747,9 @@ MemoryOps rbffi_AbstractMemoryOps = {
748
747
  void
749
748
  rbffi_AbstractMemory_Init(VALUE moduleFFI)
750
749
  {
751
- /*
750
+ /*
752
751
  * Document-class: FFI::AbstractMemory
753
- *
752
+ *
754
753
  * {AbstractMemory} is the base class for many memory management classes such as {Buffer}.
755
754
  *
756
755
  * This class has a lot of methods to work with integers :
@@ -778,8 +777,8 @@ rbffi_AbstractMemory_Init(VALUE moduleFFI)
778
777
  */
779
778
  VALUE classMemory = rb_define_class_under(moduleFFI, "AbstractMemory", rb_cObject);
780
779
  rbffi_AbstractMemoryClass = classMemory;
781
- /*
782
- * Document-variable: FFI::AbstractMemory
780
+ /*
781
+ * Document-variable: FFI::AbstractMemory
783
782
  */
784
783
  rb_global_variable(&rbffi_AbstractMemoryClass);
785
784
  rb_define_alloc_func(classMemory, memory_allocate);
@@ -807,13 +806,13 @@ rbffi_AbstractMemory_Init(VALUE moduleFFI)
807
806
  rb_define_method(classMemory, "read_array_of_" #type, memory_read_array_of_##type, 1); \
808
807
  rb_define_method(classMemory, "write_array_of_u" #type, memory_write_array_of_u##type, 1); \
809
808
  rb_define_method(classMemory, "read_array_of_u" #type, memory_read_array_of_u##type, 1);
810
-
809
+
811
810
  INT(int8);
812
811
  INT(int16);
813
812
  INT(int32);
814
813
  INT(int64);
815
814
  INT(long);
816
-
815
+
817
816
  #define ALIAS(name, old) \
818
817
  rb_define_alias(classMemory, "put_" #name, "put_" #old); \
819
818
  rb_define_alias(classMemory, "get_" #name, "get_" #old); \
@@ -831,12 +830,12 @@ rbffi_AbstractMemory_Init(VALUE moduleFFI)
831
830
  rb_define_alias(classMemory, "read_array_of_" #name, "read_array_of_" #old); \
832
831
  rb_define_alias(classMemory, "write_array_of_u" #name, "write_array_of_u" #old); \
833
832
  rb_define_alias(classMemory, "read_array_of_u" #name, "read_array_of_u" #old);
834
-
833
+
835
834
  ALIAS(char, int8);
836
835
  ALIAS(short, int16);
837
836
  ALIAS(int, int32);
838
837
  ALIAS(long_long, int64);
839
-
838
+
840
839
  /*
841
840
  * Document-method: put_float32
842
841
  * call-seq: memory.put_float32offset, value)
@@ -28,13 +28,8 @@
28
28
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
29
  */
30
30
 
31
- #ifndef _MSC_VER
32
- # include <stdint.h>
33
- # include <stdbool.h>
34
- #else
35
- # include "win32/stdbool.h"
36
- # include "win32/stdint.h"
37
- #endif
31
+ #include <stdint.h>
32
+ #include <stdbool.h>
38
33
  #include <limits.h>
39
34
  #include <ruby.h>
40
35
  #include "rbffi.h"
@@ -34,13 +34,8 @@
34
34
  #endif
35
35
  #include <sys/types.h>
36
36
  #include <stdio.h>
37
- #ifndef _MSC_VER
38
- # include <stdint.h>
39
- # include <stdbool.h>
40
- #else
41
- # include "win32/stdbool.h"
42
- # include "win32/stdint.h"
43
- #endif
37
+ #include <stdint.h>
38
+ #include <stdbool.h>
44
39
  #include <errno.h>
45
40
  #include <ruby.h>
46
41
  #include <ruby/thread.h>
@@ -34,13 +34,8 @@
34
34
  # include <sys/mman.h>
35
35
  #endif
36
36
  #include <stdio.h>
37
- #ifndef _MSC_VER
38
- # include <stdint.h>
39
- # include <stdbool.h>
40
- #else
41
- # include "win32/stdbool.h"
42
- # include "win32/stdint.h"
43
- #endif
37
+ #include <stdint.h>
38
+ #include <stdbool.h>
44
39
  #if defined(__CYGWIN__) || !defined(_WIN32)
45
40
  # include <unistd.h>
46
41
  #else
@@ -51,9 +46,6 @@
51
46
  #include <errno.h>
52
47
  #include <ruby.h>
53
48
 
54
- #if defined(_MSC_VER) && !defined(INT8_MIN)
55
- # include "win32/stdint.h"
56
- #endif
57
49
  #include <ffi.h>
58
50
  #include "rbffi.h"
59
51
  #include "compat.h"
@@ -66,7 +58,6 @@
66
58
 
67
59
  #include "ClosurePool.h"
68
60
 
69
-
70
61
  #ifndef roundup
71
62
  # define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
72
63
  #endif
@@ -115,7 +106,11 @@ cleanup_closure_pool(ClosurePool* pool)
115
106
 
116
107
  for (memory = pool->blocks; memory != NULL; ) {
117
108
  Memory* next = memory->next;
109
+ #if !USE_FFI_ALLOC
118
110
  freePage(memory->code);
111
+ #else
112
+ ffi_closure_free(memory->code);
113
+ #endif
119
114
  free(memory->data);
120
115
  free(memory);
121
116
  memory = next;
@@ -134,6 +129,8 @@ rbffi_ClosurePool_Free(ClosurePool* pool)
134
129
  }
135
130
  }
136
131
 
132
+ #if !USE_FFI_ALLOC
133
+
137
134
  Closure*
138
135
  rbffi_Closure_Alloc(ClosurePool* pool)
139
136
  {
@@ -169,6 +166,7 @@ rbffi_Closure_Alloc(ClosurePool* pool)
169
166
  closure->next = &list[i + 1];
170
167
  closure->pool = pool;
171
168
  closure->code = ((char *)code + (i * trampolineSize));
169
+ closure->pcl = closure->code;
172
170
 
173
171
  if (!(*pool->prep)(pool->ctx, closure->code, closure, errmsg, sizeof(errmsg))) {
174
172
  goto error;
@@ -205,6 +203,57 @@ error:
205
203
  return NULL;
206
204
  }
207
205
 
206
+ #else
207
+
208
+ Closure*
209
+ rbffi_Closure_Alloc(ClosurePool* pool)
210
+ {
211
+ Closure *closure = NULL;
212
+ Memory* block = NULL;
213
+ void *code = NULL;
214
+ void *pcl = NULL;
215
+ char errmsg[256];
216
+
217
+ block = calloc(1, sizeof(*block));
218
+ closure = calloc(1, sizeof(*closure));
219
+ pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
220
+
221
+ if (block == NULL || closure == NULL || pcl == NULL) {
222
+ snprintf(errmsg, sizeof(errmsg), "failed to allocate a page. errno=%d (%s)", errno, strerror(errno));
223
+ goto error;
224
+ }
225
+
226
+ closure->pool = pool;
227
+ closure->code = code;
228
+ closure->pcl = pcl;
229
+
230
+ if (!(*pool->prep)(pool->ctx, closure->code, closure, errmsg, sizeof(errmsg))) {
231
+ goto error;
232
+ }
233
+
234
+ /* Track the allocated page + Closure memory area */
235
+ block->data = closure;
236
+ block->code = pcl;
237
+ pool->blocks = block;
238
+
239
+ /* Thread the new block onto the free list, apart from the first one. */
240
+ pool->refcnt++;
241
+
242
+ return closure;
243
+
244
+ error:
245
+ free(block);
246
+ free(closure);
247
+ if (pcl != NULL) {
248
+ ffi_closure_free(pcl);
249
+ }
250
+
251
+ rb_raise(rb_eRuntimeError, "%s", errmsg);
252
+ return NULL;
253
+ }
254
+
255
+ #endif /* !USE_FFI_ALLOC */
256
+
208
257
  void
209
258
  rbffi_Closure_Free(Closure* closure)
210
259
  {
@@ -240,6 +289,8 @@ getPageSize()
240
289
  #endif
241
290
  }
242
291
 
292
+ #if !USE_FFI_ALLOC
293
+
243
294
  static void*
244
295
  allocatePage(void)
245
296
  {
@@ -272,6 +323,8 @@ protectPage(void* page)
272
323
  #endif
273
324
  }
274
325
 
326
+ #endif /* !USE_FFI_ALLOC */
327
+
275
328
  void
276
329
  rbffi_ClosurePool_Init(VALUE module)
277
330
  {
@@ -35,7 +35,9 @@ typedef struct Closure_ Closure;
35
35
  struct Closure_ {
36
36
  void* info; /* opaque handle for storing closure-instance specific data */
37
37
  void* function; /* closure-instance specific function, called by custom trampoline */
38
- void* code; /* The native trampoline code location */
38
+ void* code; /* Executable address for the native trampoline code location */
39
+ void* pcl; /* Writeable address for the native trampoline code location */
40
+
39
41
  struct ClosurePool_* pool;
40
42
  Closure* next;
41
43
  };
@@ -29,9 +29,7 @@
29
29
 
30
30
  #include <sys/types.h>
31
31
  #include <stdio.h>
32
- #ifndef _MSC_VER
33
- # include <stdint.h>
34
- #endif
32
+ #include <stdint.h>
35
33
  #if (defined(_WIN32) || defined(__WIN32__)) && !defined(__CYGWIN__)
36
34
  # include <winsock2.h>
37
35
  # define _WINSOCKAPI_
@@ -41,9 +39,6 @@
41
39
  # include <dlfcn.h>
42
40
  #endif
43
41
  #include <ruby.h>
44
- #if defined(_MSC_VER) && !defined(INT8_MIN)
45
- # include "win32/stdint.h"
46
- #endif
47
42
 
48
43
  #include <ffi.h>
49
44
 
@@ -37,15 +37,8 @@
37
37
  #endif
38
38
 
39
39
  #include <stdio.h>
40
- #ifndef _MSC_VER
41
- # include <stdint.h>
42
- # include <stdbool.h>
43
- #else
44
- # include "win32/stdbool.h"
45
- # if !defined(INT8_MIN)
46
- # include "win32/stdint.h"
47
- # endif
48
- #endif
40
+ #include <stdint.h>
41
+ #include <stdbool.h>
49
42
  #include <ruby.h>
50
43
  #include <ruby/thread.h>
51
44
 
@@ -256,11 +249,11 @@ VALUE
256
249
  rbffi_Function_ForProc(VALUE rbFunctionInfo, VALUE proc)
257
250
  {
258
251
  VALUE callback, cbref, cbTable;
259
- Function* fp;
260
252
 
261
253
  cbref = RTEST(rb_ivar_defined(proc, id_cb_ref)) ? rb_ivar_get(proc, id_cb_ref) : Qnil;
262
254
  /* If the first callback reference has the same function function signature, use it */
263
255
  if (cbref != Qnil && CLASS_OF(cbref) == rbffi_FunctionClass) {
256
+ Function* fp;
264
257
  Data_Get_Struct(cbref, Function, fp);
265
258
  if (fp->rbFunctionInfo == rbFunctionInfo) {
266
259
  return cbref;
@@ -279,8 +272,10 @@ rbffi_Function_ForProc(VALUE rbFunctionInfo, VALUE proc)
279
272
  rb_ivar_set(proc, id_cb_ref, callback);
280
273
  } else {
281
274
  /* The proc instance has been used as more than one type of callback, store extras in a hash */
282
- cbTable = rb_hash_new();
283
- rb_ivar_set(proc, id_cbtable, cbTable);
275
+ if(cbTable == Qnil) {
276
+ cbTable = rb_hash_new();
277
+ rb_ivar_set(proc, id_cbtable, cbTable);
278
+ }
284
279
  rb_hash_aset(cbTable, rbFunctionInfo, callback);
285
280
  }
286
281
 
@@ -849,7 +844,7 @@ callback_prep(void* ctx, void* code, Closure* closure, char* errmsg, size_t errm
849
844
  FunctionType* fnInfo = (FunctionType *) ctx;
850
845
  ffi_status ffiStatus;
851
846
 
852
- ffiStatus = ffi_prep_closure_loc(code, &fnInfo->ffi_cif, callback_invoke, closure, code);
847
+ ffiStatus = ffi_prep_closure_loc(closure->pcl, &fnInfo->ffi_cif, callback_invoke, closure, code);
853
848
  if (ffiStatus != FFI_OK) {
854
849
  snprintf(errmsg, errmsgsize, "ffi_prep_closure_loc failed. status=%#x", ffiStatus);
855
850
  return false;