alinta-ffi 1.9.19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (195) hide show
  1. checksums.yaml +7 -0
  2. data/COPYING +49 -0
  3. data/LICENSE +24 -0
  4. data/README.md +112 -0
  5. data/Rakefile +243 -0
  6. data/ext/ffi_c/AbstractMemory.c +1109 -0
  7. data/ext/ffi_c/AbstractMemory.h +175 -0
  8. data/ext/ffi_c/ArrayType.c +162 -0
  9. data/ext/ffi_c/ArrayType.h +59 -0
  10. data/ext/ffi_c/Buffer.c +365 -0
  11. data/ext/ffi_c/Call.c +517 -0
  12. data/ext/ffi_c/Call.h +110 -0
  13. data/ext/ffi_c/ClosurePool.c +283 -0
  14. data/ext/ffi_c/ClosurePool.h +57 -0
  15. data/ext/ffi_c/DataConverter.c +91 -0
  16. data/ext/ffi_c/DynamicLibrary.c +339 -0
  17. data/ext/ffi_c/DynamicLibrary.h +98 -0
  18. data/ext/ffi_c/Function.c +998 -0
  19. data/ext/ffi_c/Function.h +87 -0
  20. data/ext/ffi_c/FunctionInfo.c +271 -0
  21. data/ext/ffi_c/LastError.c +184 -0
  22. data/ext/ffi_c/LastError.h +47 -0
  23. data/ext/ffi_c/LongDouble.c +63 -0
  24. data/ext/ffi_c/LongDouble.h +51 -0
  25. data/ext/ffi_c/MappedType.c +168 -0
  26. data/ext/ffi_c/MappedType.h +59 -0
  27. data/ext/ffi_c/MemoryPointer.c +197 -0
  28. data/ext/ffi_c/MemoryPointer.h +53 -0
  29. data/ext/ffi_c/MethodHandle.c +358 -0
  30. data/ext/ffi_c/MethodHandle.h +55 -0
  31. data/ext/ffi_c/Platform.c +129 -0
  32. data/ext/ffi_c/Platform.h +45 -0
  33. data/ext/ffi_c/Pointer.c +508 -0
  34. data/ext/ffi_c/Pointer.h +63 -0
  35. data/ext/ffi_c/Struct.c +829 -0
  36. data/ext/ffi_c/Struct.h +106 -0
  37. data/ext/ffi_c/StructByReference.c +190 -0
  38. data/ext/ffi_c/StructByReference.h +50 -0
  39. data/ext/ffi_c/StructByValue.c +150 -0
  40. data/ext/ffi_c/StructByValue.h +55 -0
  41. data/ext/ffi_c/StructLayout.c +698 -0
  42. data/ext/ffi_c/Thread.c +352 -0
  43. data/ext/ffi_c/Thread.h +95 -0
  44. data/ext/ffi_c/Type.c +397 -0
  45. data/ext/ffi_c/Type.h +62 -0
  46. data/ext/ffi_c/Types.c +139 -0
  47. data/ext/ffi_c/Types.h +89 -0
  48. data/ext/ffi_c/Variadic.c +304 -0
  49. data/ext/ffi_c/compat.h +78 -0
  50. data/ext/ffi_c/extconf.rb +71 -0
  51. data/ext/ffi_c/ffi.c +98 -0
  52. data/ext/ffi_c/libffi.bsd.mk +40 -0
  53. data/ext/ffi_c/libffi.darwin.mk +105 -0
  54. data/ext/ffi_c/libffi.gnu.mk +32 -0
  55. data/ext/ffi_c/libffi.mk +18 -0
  56. data/ext/ffi_c/libffi.vc.mk +26 -0
  57. data/ext/ffi_c/libffi.vc64.mk +26 -0
  58. data/ext/ffi_c/rbffi.h +57 -0
  59. data/ext/ffi_c/rbffi_endian.h +59 -0
  60. data/ext/ffi_c/win32/stdbool.h +8 -0
  61. data/ext/ffi_c/win32/stdint.h +201 -0
  62. data/ffi.gemspec +23 -0
  63. data/gen/Rakefile +30 -0
  64. data/lib/ffi.rb +20 -0
  65. data/lib/ffi/autopointer.rb +203 -0
  66. data/lib/ffi/buffer.rb +4 -0
  67. data/lib/ffi/callback.rb +4 -0
  68. data/lib/ffi/enum.rb +296 -0
  69. data/lib/ffi/errno.rb +43 -0
  70. data/lib/ffi/ffi.rb +44 -0
  71. data/lib/ffi/io.rb +62 -0
  72. data/lib/ffi/library.rb +590 -0
  73. data/lib/ffi/managedstruct.rb +84 -0
  74. data/lib/ffi/memorypointer.rb +1 -0
  75. data/lib/ffi/platform.rb +164 -0
  76. data/lib/ffi/platform/aarch64-linux/types.conf +104 -0
  77. data/lib/ffi/platform/arm-linux/types.conf +104 -0
  78. data/lib/ffi/platform/i386-cygwin/types.conf +3 -0
  79. data/lib/ffi/platform/i386-darwin/types.conf +100 -0
  80. data/lib/ffi/platform/i386-freebsd/types.conf +152 -0
  81. data/lib/ffi/platform/i386-gnu/types.conf +107 -0
  82. data/lib/ffi/platform/i386-linux/types.conf +103 -0
  83. data/lib/ffi/platform/i386-netbsd/types.conf +126 -0
  84. data/lib/ffi/platform/i386-openbsd/types.conf +128 -0
  85. data/lib/ffi/platform/i386-solaris/types.conf +122 -0
  86. data/lib/ffi/platform/i386-windows/types.conf +105 -0
  87. data/lib/ffi/platform/ia64-linux/types.conf +104 -0
  88. data/lib/ffi/platform/mips-linux/types.conf +102 -0
  89. data/lib/ffi/platform/mips64el-linux/types.conf +104 -0
  90. data/lib/ffi/platform/mipsel-linux/types.conf +102 -0
  91. data/lib/ffi/platform/powerpc-aix/types.conf +180 -0
  92. data/lib/ffi/platform/powerpc-darwin/types.conf +100 -0
  93. data/lib/ffi/platform/powerpc-linux/types.conf +100 -0
  94. data/lib/ffi/platform/powerpc64-linux/types.conf +104 -0
  95. data/lib/ffi/platform/s390-linux/types.conf +102 -0
  96. data/lib/ffi/platform/s390x-linux/types.conf +102 -0
  97. data/lib/ffi/platform/sparc-linux/types.conf +102 -0
  98. data/lib/ffi/platform/sparc-solaris/types.conf +128 -0
  99. data/lib/ffi/platform/sparc64-linux/types.conf +102 -0
  100. data/lib/ffi/platform/sparcv9-solaris/types.conf +128 -0
  101. data/lib/ffi/platform/x86_64-cygwin/types.conf +3 -0
  102. data/lib/ffi/platform/x86_64-darwin/types.conf +126 -0
  103. data/lib/ffi/platform/x86_64-freebsd/types.conf +128 -0
  104. data/lib/ffi/platform/x86_64-linux/types.conf +102 -0
  105. data/lib/ffi/platform/x86_64-netbsd/types.conf +128 -0
  106. data/lib/ffi/platform/x86_64-openbsd/types.conf +134 -0
  107. data/lib/ffi/platform/x86_64-solaris/types.conf +122 -0
  108. data/lib/ffi/platform/x86_64-windows/types.conf +120 -0
  109. data/lib/ffi/pointer.rb +161 -0
  110. data/lib/ffi/struct.rb +371 -0
  111. data/lib/ffi/struct_layout_builder.rb +227 -0
  112. data/lib/ffi/tools/const_generator.rb +229 -0
  113. data/lib/ffi/tools/generator.rb +60 -0
  114. data/lib/ffi/tools/generator_task.rb +36 -0
  115. data/lib/ffi/tools/struct_generator.rb +194 -0
  116. data/lib/ffi/tools/types_generator.rb +134 -0
  117. data/lib/ffi/types.rb +194 -0
  118. data/lib/ffi/union.rb +43 -0
  119. data/lib/ffi/variadic.rb +78 -0
  120. data/lib/ffi/version.rb +4 -0
  121. data/libtest/Benchmark.c +52 -0
  122. data/libtest/BoolTest.c +34 -0
  123. data/libtest/BufferTest.c +31 -0
  124. data/libtest/ClosureTest.c +205 -0
  125. data/libtest/EnumTest.c +51 -0
  126. data/libtest/FunctionTest.c +70 -0
  127. data/libtest/GNUmakefile +149 -0
  128. data/libtest/GlobalVariable.c +62 -0
  129. data/libtest/LastErrorTest.c +21 -0
  130. data/libtest/NumberTest.c +132 -0
  131. data/libtest/PointerTest.c +63 -0
  132. data/libtest/ReferenceTest.c +23 -0
  133. data/libtest/StringTest.c +34 -0
  134. data/libtest/StructTest.c +243 -0
  135. data/libtest/UnionTest.c +43 -0
  136. data/libtest/VariadicTest.c +99 -0
  137. data/spec/ffi/LICENSE.SPECS +22 -0
  138. data/spec/ffi/async_callback_spec.rb +35 -0
  139. data/spec/ffi/bitmask_spec.rb +575 -0
  140. data/spec/ffi/bool_spec.rb +32 -0
  141. data/spec/ffi/buffer_spec.rb +279 -0
  142. data/spec/ffi/callback_spec.rb +773 -0
  143. data/spec/ffi/custom_param_type.rb +37 -0
  144. data/spec/ffi/custom_type_spec.rb +74 -0
  145. data/spec/ffi/dup_spec.rb +52 -0
  146. data/spec/ffi/enum_spec.rb +423 -0
  147. data/spec/ffi/errno_spec.rb +20 -0
  148. data/spec/ffi/ffi_spec.rb +28 -0
  149. data/spec/ffi/fixtures/Benchmark.c +52 -0
  150. data/spec/ffi/fixtures/BitmaskTest.c +51 -0
  151. data/spec/ffi/fixtures/BoolTest.c +34 -0
  152. data/spec/ffi/fixtures/BufferTest.c +31 -0
  153. data/spec/ffi/fixtures/ClosureTest.c +205 -0
  154. data/spec/ffi/fixtures/EnumTest.c +51 -0
  155. data/spec/ffi/fixtures/FunctionTest.c +142 -0
  156. data/spec/ffi/fixtures/GNUmakefile +149 -0
  157. data/spec/ffi/fixtures/GlobalVariable.c +62 -0
  158. data/spec/ffi/fixtures/LastErrorTest.c +21 -0
  159. data/spec/ffi/fixtures/NumberTest.c +132 -0
  160. data/spec/ffi/fixtures/PipeHelper.h +21 -0
  161. data/spec/ffi/fixtures/PipeHelperPosix.c +41 -0
  162. data/spec/ffi/fixtures/PipeHelperWindows.c +72 -0
  163. data/spec/ffi/fixtures/PointerTest.c +63 -0
  164. data/spec/ffi/fixtures/ReferenceTest.c +23 -0
  165. data/spec/ffi/fixtures/StringTest.c +34 -0
  166. data/spec/ffi/fixtures/StructTest.c +243 -0
  167. data/spec/ffi/fixtures/UnionTest.c +43 -0
  168. data/spec/ffi/fixtures/VariadicTest.c +99 -0
  169. data/spec/ffi/fixtures/classes.rb +438 -0
  170. data/spec/ffi/function_spec.rb +97 -0
  171. data/spec/ffi/io_spec.rb +16 -0
  172. data/spec/ffi/library_spec.rb +286 -0
  173. data/spec/ffi/long_double.rb +30 -0
  174. data/spec/ffi/managed_struct_spec.rb +68 -0
  175. data/spec/ffi/memorypointer_spec.rb +78 -0
  176. data/spec/ffi/number_spec.rb +247 -0
  177. data/spec/ffi/platform_spec.rb +114 -0
  178. data/spec/ffi/pointer_spec.rb +285 -0
  179. data/spec/ffi/rbx/attach_function_spec.rb +34 -0
  180. data/spec/ffi/rbx/memory_pointer_spec.rb +198 -0
  181. data/spec/ffi/rbx/spec_helper.rb +6 -0
  182. data/spec/ffi/rbx/struct_spec.rb +18 -0
  183. data/spec/ffi/spec_helper.rb +93 -0
  184. data/spec/ffi/string_spec.rb +118 -0
  185. data/spec/ffi/strptr_spec.rb +50 -0
  186. data/spec/ffi/struct_by_ref_spec.rb +43 -0
  187. data/spec/ffi/struct_callback_spec.rb +69 -0
  188. data/spec/ffi/struct_initialize_spec.rb +35 -0
  189. data/spec/ffi/struct_packed_spec.rb +50 -0
  190. data/spec/ffi/struct_spec.rb +882 -0
  191. data/spec/ffi/typedef_spec.rb +91 -0
  192. data/spec/ffi/union_spec.rb +67 -0
  193. data/spec/ffi/variadic_spec.rb +132 -0
  194. data/spec/spec.opts +4 -0
  195. metadata +309 -0
@@ -0,0 +1,53 @@
1
+ /*
2
+ * Copyright (c) 2008, 2009, Wayne Meissner
3
+ * Copyright (c) 2008, Luc Heinrich <luc@honk-honk.com>
4
+ *
5
+ * Copyright (c) 2008-2013, Ruby FFI project contributors
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without
9
+ * modification, are permitted provided that the following conditions are met:
10
+ * * Redistributions of source code must retain the above copyright
11
+ * notice, this list of conditions and the following disclaimer.
12
+ * * Redistributions in binary form must reproduce the above copyright
13
+ * notice, this list of conditions and the following disclaimer in the
14
+ * documentation and/or other materials provided with the distribution.
15
+ * * Neither the name of the Ruby FFI project nor the
16
+ * names of its contributors may be used to endorse or promote products
17
+ * derived from this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
23
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ */
30
+
31
+ #ifndef RBFFI_MEMORYPOINTER_H
32
+ #define RBFFI_MEMORYPOINTER_H
33
+
34
+ #ifndef _MSC_VER
35
+ # include <stdbool.h>
36
+ #else
37
+ # include "win32/stdbool.h"
38
+ #endif
39
+ #include <ruby.h>
40
+
41
+ #ifdef __cplusplus
42
+ extern "C" {
43
+ #endif
44
+
45
+ extern void rbffi_MemoryPointer_Init(VALUE moduleFFI);
46
+ extern VALUE rbffi_MemoryPointerClass;
47
+ extern VALUE rbffi_MemoryPointer_NewInstance(long size, long count, bool clear);
48
+ #ifdef __cplusplus
49
+ }
50
+ #endif
51
+
52
+ #endif /* RBFFI_MEMORYPOINTER_H */
53
+
@@ -0,0 +1,358 @@
1
+ /*
2
+ * Copyright (c) 2009, 2010 Wayne Meissner
3
+ * Copyright (c) 2008-2013, Ruby FFI project contributors
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of the Ruby FFI project nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+
29
+ #ifndef _MSC_VER
30
+ #include <sys/param.h>
31
+ #endif
32
+ #include <sys/types.h>
33
+ #ifndef _WIN32
34
+ # include <sys/mman.h>
35
+ #endif
36
+ #include <stdio.h>
37
+ #ifndef _MSC_VER
38
+ # include <stdint.h>
39
+ # include <stdbool.h>
40
+ #else
41
+ # include "win32/stdint.h"
42
+ # include "win32/stdbool.h"
43
+ #endif
44
+ #ifndef _WIN32
45
+ # include <unistd.h>
46
+ #endif
47
+ #include <errno.h>
48
+ #include <ruby.h>
49
+ #if defined(HAVE_NATIVETHREAD) && !defined(_WIN32) && !defined(__WIN32__)
50
+ # include <pthread.h>
51
+ #endif
52
+
53
+ #include <ffi.h>
54
+ #include "rbffi.h"
55
+ #include "compat.h"
56
+
57
+ #include "Function.h"
58
+ #include "Types.h"
59
+ #include "Type.h"
60
+ #include "LastError.h"
61
+ #include "Call.h"
62
+ #include "ClosurePool.h"
63
+ #include "MethodHandle.h"
64
+
65
+
66
+ #define MAX_METHOD_FIXED_ARITY (6)
67
+
68
+ #ifndef roundup
69
+ # define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
70
+ #endif
71
+ #ifdef _WIN32
72
+ typedef char* caddr_t;
73
+ #endif
74
+
75
+ #ifdef USE_RAW
76
+ # define METHOD_CLOSURE ffi_raw_closure
77
+ # define METHOD_PARAMS ffi_raw*
78
+ #else
79
+ # define METHOD_CLOSURE ffi_closure
80
+ # define METHOD_PARAMS void**
81
+ #endif
82
+
83
+
84
+
85
+ static bool prep_trampoline(void* ctx, void* code, Closure* closure, char* errmsg, size_t errmsgsize);
86
+ static long trampoline_size(void);
87
+
88
+ #if defined(__x86_64__) && (defined(__linux__) || defined(__APPLE__))
89
+ # define CUSTOM_TRAMPOLINE 1
90
+ #endif
91
+
92
+
93
+ struct MethodHandle {
94
+ Closure* closure;
95
+ };
96
+
97
+ static ClosurePool* defaultClosurePool;
98
+
99
+
100
+ MethodHandle*
101
+ rbffi_MethodHandle_Alloc(FunctionType* fnInfo, void* function)
102
+ {
103
+ MethodHandle* handle;
104
+ Closure* closure = rbffi_Closure_Alloc(defaultClosurePool);
105
+ if (closure == NULL) {
106
+ rb_raise(rb_eNoMemError, "failed to allocate closure from pool");
107
+ return NULL;
108
+ }
109
+
110
+ handle = xcalloc(1, sizeof(*handle));
111
+ handle->closure = closure;
112
+ closure->info = fnInfo;
113
+ closure->function = function;
114
+
115
+ return handle;
116
+ }
117
+
118
+ void
119
+ rbffi_MethodHandle_Free(MethodHandle* handle)
120
+ {
121
+ if (handle != NULL) {
122
+ rbffi_Closure_Free(handle->closure);
123
+ }
124
+ }
125
+
126
+ void*
127
+ rbffi_MethodHandle_CodeAddress(MethodHandle* handle)
128
+ {
129
+ return handle->closure->code;
130
+ }
131
+
132
+ #ifndef CUSTOM_TRAMPOLINE
133
+ static void attached_method_invoke(ffi_cif* cif, void* retval, METHOD_PARAMS parameters, void* user_data);
134
+
135
+ static ffi_type* methodHandleParamTypes[] = {
136
+ &ffi_type_sint,
137
+ &ffi_type_pointer,
138
+ &ffi_type_ulong,
139
+ };
140
+
141
+ static ffi_cif mh_cif;
142
+
143
+ static bool
144
+ prep_trampoline(void* ctx, void* code, Closure* closure, char* errmsg, size_t errmsgsize)
145
+ {
146
+ ffi_status ffiStatus;
147
+
148
+ #if defined(USE_RAW)
149
+ ffiStatus = ffi_prep_raw_closure(code, &mh_cif, attached_method_invoke, closure);
150
+ #else
151
+ ffiStatus = ffi_prep_closure(code, &mh_cif, attached_method_invoke, closure);
152
+ #endif
153
+ if (ffiStatus != FFI_OK) {
154
+ snprintf(errmsg, errmsgsize, "ffi_prep_closure failed. status=%#x", ffiStatus);
155
+ return false;
156
+ }
157
+
158
+ return true;
159
+ }
160
+
161
+
162
+ static long
163
+ trampoline_size(void)
164
+ {
165
+ return sizeof(METHOD_CLOSURE);
166
+ }
167
+
168
+ /*
169
+ * attached_method_invoke is used functions with more than 6 parameters, or
170
+ * with struct param or return values
171
+ */
172
+ static void
173
+ attached_method_invoke(ffi_cif* cif, void* mretval, METHOD_PARAMS parameters, void* user_data)
174
+ {
175
+ Closure* handle = (Closure *) user_data;
176
+ FunctionType* fnInfo = (FunctionType *) handle->info;
177
+
178
+ #ifdef USE_RAW
179
+ int argc = parameters[0].sint;
180
+ VALUE* argv = *(VALUE **) &parameters[1];
181
+ #else
182
+ int argc = *(int *) parameters[0];
183
+ VALUE* argv = *(VALUE **) parameters[1];
184
+ #endif
185
+
186
+ *(VALUE *) mretval = (*fnInfo->invoke)(argc, argv, handle->function, fnInfo);
187
+ }
188
+
189
+ #endif
190
+
191
+
192
+
193
+ #if defined(CUSTOM_TRAMPOLINE)
194
+ #if defined(__x86_64__)
195
+
196
+ static VALUE custom_trampoline(int argc, VALUE* argv, VALUE self, Closure*);
197
+
198
+ #define TRAMPOLINE_CTX_MAGIC (0xfee1deadcafebabe)
199
+ #define TRAMPOLINE_FUN_MAGIC (0xfeedfacebeeff00d)
200
+
201
+ /*
202
+ * This is a hand-coded trampoline to speedup entry from ruby to the FFI translation
203
+ * layer for x86_64 arches.
204
+ *
205
+ * Since a ruby function has exactly 3 arguments, and the first 6 arguments are
206
+ * passed in registers for x86_64, we can tack on a context pointer by simply
207
+ * putting a value in %rcx, then jumping to the C trampoline code.
208
+ *
209
+ * This results in approx a 30% speedup for x86_64 FFI dispatch
210
+ */
211
+ __asm__(
212
+ ".text\n\t"
213
+ ".globl ffi_trampoline\n\t"
214
+ ".globl _ffi_trampoline\n\t"
215
+ "ffi_trampoline:\n\t"
216
+ "_ffi_trampoline:\n\t"
217
+ "movabsq $0xfee1deadcafebabe, %rcx\n\t"
218
+ "movabsq $0xfeedfacebeeff00d, %r11\n\t"
219
+ "jmpq *%r11\n\t"
220
+ ".globl ffi_trampoline_end\n\t"
221
+ "ffi_trampoline_end:\n\t"
222
+ ".globl _ffi_trampoline_end\n\t"
223
+ "_ffi_trampoline_end:\n\t"
224
+ );
225
+
226
+ static VALUE
227
+ custom_trampoline(int argc, VALUE* argv, VALUE self, Closure* handle)
228
+ {
229
+ FunctionType* fnInfo = (FunctionType *) handle->info;
230
+ VALUE rbReturnValue;
231
+
232
+ RB_GC_GUARD(rbReturnValue) = (*fnInfo->invoke)(argc, argv, handle->function, fnInfo);
233
+ RB_GC_GUARD(self);
234
+
235
+ return rbReturnValue;
236
+ }
237
+
238
+ #elif defined(__i386__) && 0
239
+
240
+ static VALUE custom_trampoline(caddr_t args, Closure*);
241
+ #define TRAMPOLINE_CTX_MAGIC (0xfee1dead)
242
+ #define TRAMPOLINE_FUN_MAGIC (0xbeefcafe)
243
+
244
+ /*
245
+ * This is a hand-coded trampoline to speed-up entry from ruby to the FFI translation
246
+ * layer for i386 arches.
247
+ *
248
+ * This does not make a discernible difference vs a raw closure, so for now,
249
+ * it is not enabled.
250
+ */
251
+ __asm__(
252
+ ".text\n\t"
253
+ ".globl ffi_trampoline\n\t"
254
+ ".globl _ffi_trampoline\n\t"
255
+ "ffi_trampoline:\n\t"
256
+ "_ffi_trampoline:\n\t"
257
+ "subl $12, %esp\n\t"
258
+ "leal 16(%esp), %eax\n\t"
259
+ "movl %eax, (%esp)\n\t"
260
+ "movl $0xfee1dead, 4(%esp)\n\t"
261
+ "movl $0xbeefcafe, %eax\n\t"
262
+ "call *%eax\n\t"
263
+ "addl $12, %esp\n\t"
264
+ "ret\n\t"
265
+ ".globl ffi_trampoline_end\n\t"
266
+ "ffi_trampoline_end:\n\t"
267
+ ".globl _ffi_trampoline_end\n\t"
268
+ "_ffi_trampoline_end:\n\t"
269
+ );
270
+
271
+ static VALUE
272
+ custom_trampoline(caddr_t args, Closure* handle)
273
+ {
274
+ FunctionType* fnInfo = (FunctionType *) handle->info;
275
+ return (*fnInfo->invoke)(*(int *) args, *(VALUE **) (args + 4), handle->function, fnInfo);
276
+ }
277
+
278
+ #endif /* __x86_64__ else __i386__ */
279
+
280
+ extern void ffi_trampoline(int argc, VALUE* argv, VALUE self);
281
+ extern void ffi_trampoline_end(void);
282
+ static int trampoline_offsets(long *, long *);
283
+
284
+ static long trampoline_ctx_offset, trampoline_func_offset;
285
+
286
+ static long
287
+ trampoline_offset(int off, const long value)
288
+ {
289
+ caddr_t ptr;
290
+ for (ptr = (caddr_t) &ffi_trampoline + off; ptr < (caddr_t) &ffi_trampoline_end; ++ptr) {
291
+ if (*(long *) ptr == value) {
292
+ return ptr - (caddr_t) &ffi_trampoline;
293
+ }
294
+ }
295
+
296
+ return -1;
297
+ }
298
+
299
+ static int
300
+ trampoline_offsets(long* ctxOffset, long* fnOffset)
301
+ {
302
+ *ctxOffset = trampoline_offset(0, TRAMPOLINE_CTX_MAGIC);
303
+ if (*ctxOffset == -1) {
304
+ return -1;
305
+ }
306
+
307
+ *fnOffset = trampoline_offset(0, TRAMPOLINE_FUN_MAGIC);
308
+ if (*fnOffset == -1) {
309
+ return -1;
310
+ }
311
+
312
+ return 0;
313
+ }
314
+
315
+ static bool
316
+ prep_trampoline(void* ctx, void* code, Closure* closure, char* errmsg, size_t errmsgsize)
317
+ {
318
+ caddr_t ptr = (caddr_t) code;
319
+
320
+ memcpy(ptr, &ffi_trampoline, trampoline_size());
321
+ /* Patch the context and function addresses into the stub code */
322
+ *(intptr_t *)(ptr + trampoline_ctx_offset) = (intptr_t) closure;
323
+ *(intptr_t *)(ptr + trampoline_func_offset) = (intptr_t) custom_trampoline;
324
+
325
+ return true;
326
+ }
327
+
328
+ static long
329
+ trampoline_size(void)
330
+ {
331
+ return (caddr_t) &ffi_trampoline_end - (caddr_t) &ffi_trampoline;
332
+ }
333
+
334
+ #endif /* CUSTOM_TRAMPOLINE */
335
+
336
+
337
+ void
338
+ rbffi_MethodHandle_Init(VALUE module)
339
+ {
340
+ #ifndef CUSTOM_TRAMPOLINE
341
+ ffi_status ffiStatus;
342
+ #endif
343
+
344
+ defaultClosurePool = rbffi_ClosurePool_New((int) trampoline_size(), prep_trampoline, NULL);
345
+
346
+ #if defined(CUSTOM_TRAMPOLINE)
347
+ if (trampoline_offsets(&trampoline_ctx_offset, &trampoline_func_offset) != 0) {
348
+ rb_raise(rb_eFatal, "Could not locate offsets in trampoline code");
349
+ }
350
+ #else
351
+ ffiStatus = ffi_prep_cif(&mh_cif, FFI_DEFAULT_ABI, 3, &ffi_type_ulong,
352
+ methodHandleParamTypes);
353
+ if (ffiStatus != FFI_OK) {
354
+ rb_raise(rb_eFatal, "ffi_prep_cif failed. status=%#x", ffiStatus);
355
+ }
356
+
357
+ #endif
358
+ }
@@ -0,0 +1,55 @@
1
+ /*
2
+ * Copyright (c) 2009, Wayne Meissner
3
+ *
4
+ * Copyright (c) 2008-2013, Ruby FFI project contributors
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions are met:
9
+ * * Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ * * Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ * * Neither the name of the Ruby FFI project nor the
15
+ * names of its contributors may be used to endorse or promote products
16
+ * derived from this software without specific prior written permission.
17
+ *
18
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
22
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ */
29
+
30
+ #ifndef RBFFI_METHODHANDLE_H
31
+ #define RBFFI_METHODHANDLE_H
32
+
33
+ #ifdef __cplusplus
34
+ extern "C" {
35
+ #endif
36
+
37
+ #include <ruby.h>
38
+ #include "Function.h"
39
+
40
+
41
+ typedef struct MethodHandlePool MethodHandlePool;
42
+ typedef struct MethodHandle MethodHandle;
43
+
44
+
45
+ MethodHandle* rbffi_MethodHandle_Alloc(FunctionType* fnInfo, void* function);
46
+ void rbffi_MethodHandle_Free(MethodHandle* handle);
47
+ void* rbffi_MethodHandle_CodeAddress(MethodHandle* handle);
48
+ void rbffi_MethodHandle_Init(VALUE module);
49
+
50
+ #ifdef __cplusplus
51
+ }
52
+ #endif
53
+
54
+ #endif /* RBFFI_METHODHANDLE_H */
55
+