ruby-libjit 0.1.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.
- data/COPYING +6 -0
- data/LGPL +515 -0
- data/LICENSE +20 -0
- data/README +50 -0
- data/ext/extconf.rb +100 -0
- data/ext/insns.inc.rpp +204 -0
- data/ext/jit.c +1521 -0
- data/ext/method_data.c +385 -0
- data/ext/method_data.c.rpp +294 -0
- data/ext/method_data.h +11 -0
- data/ext/minimal_node.c +35 -0
- data/ext/minimal_node.h +52 -0
- data/ext/rubyjit.h +20 -0
- data/ext/rubypp.rb +97 -0
- data/lib/jit/array.rb +135 -0
- data/lib/jit/function.rb +201 -0
- data/lib/jit/struct.rb +163 -0
- data/lib/jit/value.rb +199 -0
- data/lib/jit.rb +5 -0
- data/sample/fib.rb +29 -0
- data/sample/gcd_benchmark.rb +117 -0
- data/sample/simple.rb +15 -0
- data/test/test_jit_array.rb +70 -0
- data/test/test_jit_function.rb +329 -0
- data/test/test_jit_struct.rb +111 -0
- data/test/test_jit_value.rb +258 -0
- metadata +77 -0
data/ext/jit.c
ADDED
@@ -0,0 +1,1521 @@
|
|
1
|
+
#ifndef RUBY_DEFINES_GNU_SOURCE
|
2
|
+
#define _GNU_SOURCE
|
3
|
+
#endif
|
4
|
+
|
5
|
+
#include <ruby.h>
|
6
|
+
|
7
|
+
#include <stdio.h>
|
8
|
+
|
9
|
+
#include <jit/jit.h>
|
10
|
+
#include <jit/jit-dump.h>
|
11
|
+
|
12
|
+
#include "rubyjit.h"
|
13
|
+
#include "method_data.h"
|
14
|
+
|
15
|
+
#ifdef NEED_MINIMAL_NODE
|
16
|
+
#include "minimal_node.h"
|
17
|
+
#endif
|
18
|
+
|
19
|
+
static VALUE rb_mJIT;
|
20
|
+
static VALUE rb_cContext;
|
21
|
+
static VALUE rb_cFunction;
|
22
|
+
static VALUE rb_cType;
|
23
|
+
static VALUE rb_mABI;
|
24
|
+
static VALUE rb_cValue;
|
25
|
+
static VALUE rb_cLabel;
|
26
|
+
static VALUE rb_mCall;
|
27
|
+
static VALUE rb_cClosure;
|
28
|
+
|
29
|
+
jit_type_t jit_type_VALUE;
|
30
|
+
jit_type_t jit_type_ID;
|
31
|
+
jit_type_t jit_type_Function_Ptr;
|
32
|
+
|
33
|
+
static jit_type_t ruby_vararg_signature;
|
34
|
+
|
35
|
+
typedef void (*Void_Function_Ptr)();
|
36
|
+
|
37
|
+
struct Closure
|
38
|
+
{
|
39
|
+
VALUE function;
|
40
|
+
Void_Function_Ptr function_ptr;
|
41
|
+
};
|
42
|
+
|
43
|
+
#ifdef VALUE_IS_PTR
|
44
|
+
/* Rubinius */
|
45
|
+
typedef jit_ptr jit_VALUE;
|
46
|
+
#define jit_underlying_type_VALUE jit_type_void_ptr
|
47
|
+
#define SET_CONSTANT_VALUE(c, v) (c.un.ptr_value = v)
|
48
|
+
|
49
|
+
#elif SIZEOF_VALUE == 4
|
50
|
+
/* 32-bit */
|
51
|
+
typedef jit_uint jit_VALUE;
|
52
|
+
#define jit_underlying_type_VALUE jit_type_uint
|
53
|
+
#define SET_CONSTANT_VALUE(c, v) (c.un.uint_value = v)
|
54
|
+
|
55
|
+
#elif SIZEOF_VALUE == 8
|
56
|
+
/* 64-bit */
|
57
|
+
typedef jit_ulong jit_VALUE;
|
58
|
+
#define jit_underlying_type_VALUE jit_type_ulong
|
59
|
+
#define SET_CONSTANT_VALUE(c, v) (c.un.ulong_value = v)
|
60
|
+
|
61
|
+
#else
|
62
|
+
#error "Unsupported size for VALUE"
|
63
|
+
#endif
|
64
|
+
|
65
|
+
#if SIZEOF_ID == 4
|
66
|
+
/* 32-bit */
|
67
|
+
typedef jit_uint jit_ID;
|
68
|
+
#define jit_underlying_type_ID jit_type_uint
|
69
|
+
#define SET_CONSTANT_ID(c, v) (c.un.uint_value = v)
|
70
|
+
#elif SIZEOF_ID == 8
|
71
|
+
/* 64-bit */
|
72
|
+
typedef jit_ulong jit_ID;
|
73
|
+
#define jit_underlying_type_ID jit_type_ulong
|
74
|
+
#define SET_CONSTANT_ID(c, v) (c.un.ulong_value = v)
|
75
|
+
#else
|
76
|
+
#error "Unsupported size for ID"
|
77
|
+
#endif
|
78
|
+
|
79
|
+
typedef jit_ptr jit_Function_Ptr;
|
80
|
+
#define jit_underlying_type_void_ptr jit_type_void_ptr
|
81
|
+
#define SET_FUNCTION_POINTER_VALUE(c, v) (c.un.ptr_value = v)
|
82
|
+
|
83
|
+
#ifdef HAVE_RB_ERRINFO
|
84
|
+
#define ruby_errinfo rb_errinfo()
|
85
|
+
#endif
|
86
|
+
|
87
|
+
/* ---------------------------------------------------------------------------
|
88
|
+
* Utility functions
|
89
|
+
* ---------------------------------------------------------------------------
|
90
|
+
*/
|
91
|
+
|
92
|
+
static void check_type(char const * param_name, VALUE expected_klass, VALUE val)
|
93
|
+
{
|
94
|
+
if(!rb_obj_is_kind_of(val, expected_klass))
|
95
|
+
{
|
96
|
+
rb_raise(
|
97
|
+
rb_eTypeError,
|
98
|
+
"Wrong type for %s; expected %s but got %s",
|
99
|
+
param_name,
|
100
|
+
rb_class2name(expected_klass),
|
101
|
+
rb_class2name(CLASS_OF(val)));
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
void raise_memory_error_if_zero(void * v)
|
106
|
+
{
|
107
|
+
if(!v)
|
108
|
+
{
|
109
|
+
rb_raise(rb_eNoMemError, "Out of memory");
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
/* ---------------------------------------------------------------------------
|
114
|
+
* Context
|
115
|
+
* ---------------------------------------------------------------------------
|
116
|
+
*/
|
117
|
+
|
118
|
+
static void context_mark(jit_context_t context)
|
119
|
+
{
|
120
|
+
VALUE functions = (VALUE)jit_context_get_meta(context, RJT_FUNCTIONS);
|
121
|
+
rb_gc_mark(functions);
|
122
|
+
}
|
123
|
+
|
124
|
+
/*
|
125
|
+
* call-seq:
|
126
|
+
* context = Context.new
|
127
|
+
*
|
128
|
+
* Create a new context.
|
129
|
+
*/
|
130
|
+
static VALUE context_s_new(VALUE klass)
|
131
|
+
{
|
132
|
+
jit_context_t context = jit_context_create();
|
133
|
+
jit_context_set_meta(context, RJT_FUNCTIONS, (void*)rb_ary_new(), 0);
|
134
|
+
return Data_Wrap_Struct(rb_cContext, context_mark, jit_context_destroy, context);
|
135
|
+
}
|
136
|
+
|
137
|
+
/*
|
138
|
+
* call-seq:
|
139
|
+
* context.build { ... }
|
140
|
+
*
|
141
|
+
* Acquire a lock on the context so it can be used to build a function.
|
142
|
+
*/
|
143
|
+
static VALUE context_build(VALUE self)
|
144
|
+
{
|
145
|
+
jit_context_t context;
|
146
|
+
Data_Get_Struct(self, struct _jit_context, context);
|
147
|
+
jit_context_build_start(context);
|
148
|
+
#ifdef HAVE_RB_ENSURE
|
149
|
+
return rb_ensure(
|
150
|
+
rb_yield,
|
151
|
+
self,
|
152
|
+
RUBY_METHOD_FUNC(jit_context_build_end),
|
153
|
+
(VALUE)context);
|
154
|
+
#else
|
155
|
+
/* Rubinius does not yet have rb_ensure */
|
156
|
+
rb_yield(self);
|
157
|
+
jit_context_build_end(context);
|
158
|
+
#endif
|
159
|
+
}
|
160
|
+
|
161
|
+
/*
|
162
|
+
* call-seq:
|
163
|
+
* Context.build { |context| ... }
|
164
|
+
*
|
165
|
+
* Create a context and acquire a lock on it, then yield the context to
|
166
|
+
* the block.
|
167
|
+
*/
|
168
|
+
static VALUE context_s_build(VALUE klass)
|
169
|
+
{
|
170
|
+
return context_build(context_s_new(klass));
|
171
|
+
}
|
172
|
+
|
173
|
+
/* ---------------------------------------------------------------------------
|
174
|
+
* Closure
|
175
|
+
* ---------------------------------------------------------------------------
|
176
|
+
*/
|
177
|
+
|
178
|
+
static void mark_closure(struct Closure * closure)
|
179
|
+
{
|
180
|
+
rb_gc_mark(closure->function);
|
181
|
+
}
|
182
|
+
|
183
|
+
VALUE closure_to_int(VALUE self)
|
184
|
+
{
|
185
|
+
struct Closure * closure;
|
186
|
+
Data_Get_Struct(self, struct Closure, closure);
|
187
|
+
VALUE v = ULONG2NUM((unsigned long)closure->function_ptr);
|
188
|
+
return v;
|
189
|
+
}
|
190
|
+
|
191
|
+
VALUE closure_to_s(VALUE self)
|
192
|
+
{
|
193
|
+
struct Closure * closure;
|
194
|
+
VALUE args[4];
|
195
|
+
Data_Get_Struct(self, struct Closure, closure);
|
196
|
+
args[0] = rb_str_new2("#<JIT::Closure:0x%x function=%s function_ptr=0x%x>");
|
197
|
+
args[1] = ULONG2NUM((unsigned long)self);
|
198
|
+
args[2] = rb_any_to_s(closure->function);
|
199
|
+
args[3] = ULONG2NUM((unsigned long)closure->function_ptr);
|
200
|
+
return rb_f_sprintf(sizeof(args)/sizeof(args[0]), args);
|
201
|
+
}
|
202
|
+
|
203
|
+
VALUE closure_inspect(VALUE self)
|
204
|
+
{
|
205
|
+
return closure_to_s(self);
|
206
|
+
}
|
207
|
+
|
208
|
+
/* ---------------------------------------------------------------------------
|
209
|
+
* Function
|
210
|
+
* ---------------------------------------------------------------------------
|
211
|
+
*/
|
212
|
+
|
213
|
+
static void mark_function(jit_function_t function)
|
214
|
+
{
|
215
|
+
rb_gc_mark((VALUE)jit_function_get_meta(function, RJT_VALUE_OBJECTS));
|
216
|
+
rb_gc_mark((VALUE)jit_function_get_meta(function, RJT_CONTEXT));
|
217
|
+
}
|
218
|
+
|
219
|
+
static VALUE create_function(int argc, VALUE * argv, VALUE klass)
|
220
|
+
{
|
221
|
+
VALUE context_v;
|
222
|
+
VALUE signature_v;
|
223
|
+
VALUE parent_function_v;
|
224
|
+
|
225
|
+
jit_function_t function;
|
226
|
+
jit_function_t parent_function;
|
227
|
+
jit_context_t context;
|
228
|
+
jit_type_t signature;
|
229
|
+
jit_type_t untagged_signature;
|
230
|
+
|
231
|
+
VALUE function_v;
|
232
|
+
VALUE functions;
|
233
|
+
|
234
|
+
int signature_tag;
|
235
|
+
|
236
|
+
rb_scan_args(argc, argv, "21", &context_v, &signature_v, &parent_function_v);
|
237
|
+
|
238
|
+
Data_Get_Struct(context_v, struct _jit_context, context);
|
239
|
+
Data_Get_Struct(signature_v, struct _jit_type, signature);
|
240
|
+
|
241
|
+
signature_tag = jit_type_get_kind(signature);
|
242
|
+
|
243
|
+
/* If this signature was tagged, get the untagged type */
|
244
|
+
if((untagged_signature = jit_type_get_tagged_type(signature)))
|
245
|
+
{
|
246
|
+
signature = untagged_signature;
|
247
|
+
}
|
248
|
+
|
249
|
+
if(RTEST(parent_function_v))
|
250
|
+
{
|
251
|
+
/* If this function has a parent, then it is a nested function */
|
252
|
+
Data_Get_Struct(parent_function_v, struct _jit_function, parent_function);
|
253
|
+
function = jit_function_create_nested(context, signature, parent_function);
|
254
|
+
}
|
255
|
+
else
|
256
|
+
{
|
257
|
+
/* Otherwise, it's a standalone function */
|
258
|
+
function = jit_function_create(context, signature);
|
259
|
+
}
|
260
|
+
|
261
|
+
/* Make sure the function is around as long as the context is */
|
262
|
+
if(!jit_function_set_meta(function, RJT_VALUE_OBJECTS, (void *)rb_ary_new(), 0, 0))
|
263
|
+
{
|
264
|
+
rb_raise(rb_eNoMemError, "Out of memory");
|
265
|
+
}
|
266
|
+
|
267
|
+
/* Remember the signature's tag for later */
|
268
|
+
if(!jit_function_set_meta(function, RJT_TAG_FOR_SIGNATURE, (void *)signature_tag, 0, 0))
|
269
|
+
{
|
270
|
+
rb_raise(rb_eNoMemError, "Out of memory");
|
271
|
+
}
|
272
|
+
|
273
|
+
/* And remember the function's context for later */
|
274
|
+
if(!jit_function_set_meta(function, RJT_CONTEXT, (void *)context_v, 0, 0))
|
275
|
+
{
|
276
|
+
rb_raise(rb_eNoMemError, "Out of memory");
|
277
|
+
}
|
278
|
+
|
279
|
+
function_v = Data_Wrap_Struct(rb_cFunction, mark_function, 0, function);
|
280
|
+
|
281
|
+
/* Add this function to the context's list of functions */
|
282
|
+
functions = (VALUE)jit_context_get_meta(context, RJT_FUNCTIONS);
|
283
|
+
rb_ary_push(functions, function_v);
|
284
|
+
|
285
|
+
return function_v;
|
286
|
+
}
|
287
|
+
|
288
|
+
/*
|
289
|
+
* call-seq:
|
290
|
+
* function.compile()
|
291
|
+
*
|
292
|
+
* Begin compiling a function.
|
293
|
+
*/
|
294
|
+
static VALUE function_compile(VALUE self)
|
295
|
+
{
|
296
|
+
jit_function_t function;
|
297
|
+
Data_Get_Struct(self, struct _jit_function, function);
|
298
|
+
if(!jit_function_compile(function))
|
299
|
+
{
|
300
|
+
rb_raise(rb_eRuntimeError, "Unable to compile function");
|
301
|
+
}
|
302
|
+
return self;
|
303
|
+
}
|
304
|
+
|
305
|
+
/*
|
306
|
+
* call-seq:
|
307
|
+
* function = Function.new(context, signature, [parent])
|
308
|
+
*
|
309
|
+
* Create a new function.
|
310
|
+
*/
|
311
|
+
static VALUE function_s_new(int argc, VALUE * argv, VALUE klass)
|
312
|
+
{
|
313
|
+
if(rb_block_given_p())
|
314
|
+
{
|
315
|
+
rb_raise(rb_eArgError, "Function.new does not take a block");
|
316
|
+
}
|
317
|
+
|
318
|
+
return create_function(argc, argv, klass);
|
319
|
+
}
|
320
|
+
|
321
|
+
static VALUE function_abandon_if_exception(VALUE function_v)
|
322
|
+
{
|
323
|
+
if(ruby_errinfo)
|
324
|
+
{
|
325
|
+
jit_function_t function;
|
326
|
+
Data_Get_Struct(function_v, struct _jit_function, function);
|
327
|
+
jit_function_abandon(function);
|
328
|
+
}
|
329
|
+
return Qnil;
|
330
|
+
}
|
331
|
+
|
332
|
+
/*
|
333
|
+
* call-seq:
|
334
|
+
* function = Function.new(context, signature, [parent]) { |function| ... }
|
335
|
+
*
|
336
|
+
* Create a new function, begin compiling it, and pass the function to
|
337
|
+
* the block.
|
338
|
+
*/
|
339
|
+
static VALUE function_s_compile(int argc, VALUE * argv, VALUE klass)
|
340
|
+
{
|
341
|
+
VALUE function = create_function(argc, argv, klass);
|
342
|
+
rb_yield(function);
|
343
|
+
function_compile(function);
|
344
|
+
#ifdef HAVE_RB_ENSURE
|
345
|
+
rb_ensure(
|
346
|
+
function_compile,
|
347
|
+
function,
|
348
|
+
function_abandon_if_exception,
|
349
|
+
function);
|
350
|
+
#else
|
351
|
+
/* Rubinius does not yet have rb_ensure */
|
352
|
+
function_compile(function);
|
353
|
+
function_abandon_if_exception(function);
|
354
|
+
#endif
|
355
|
+
return function;
|
356
|
+
}
|
357
|
+
|
358
|
+
/*
|
359
|
+
* Get the value that corresponds to a specified function parameter.
|
360
|
+
*
|
361
|
+
* call-seq:
|
362
|
+
* value = function.get_param(index)
|
363
|
+
*/
|
364
|
+
static VALUE function_get_param(VALUE self, VALUE idx)
|
365
|
+
{
|
366
|
+
jit_function_t function;
|
367
|
+
jit_value_t value;
|
368
|
+
Data_Get_Struct(self, struct _jit_function, function);
|
369
|
+
value = jit_value_get_param(function, NUM2INT(idx));
|
370
|
+
raise_memory_error_if_zero(value);
|
371
|
+
return Data_Wrap_Struct(rb_cValue, 0, 0, value);
|
372
|
+
}
|
373
|
+
|
374
|
+
#include "insns.inc"
|
375
|
+
|
376
|
+
static VALUE function_value_klass(VALUE self, VALUE type_v, VALUE klass)
|
377
|
+
{
|
378
|
+
jit_function_t function;
|
379
|
+
jit_type_t type;
|
380
|
+
jit_value_t value;
|
381
|
+
|
382
|
+
Data_Get_Struct(self, struct _jit_function, function);
|
383
|
+
|
384
|
+
check_type("type", rb_cType, type_v);
|
385
|
+
Data_Get_Struct(type_v, struct _jit_type, type);
|
386
|
+
|
387
|
+
/* TODO: When we wrap a value, we should inject a reference to the
|
388
|
+
* function in the object, so the function stays around as long as the
|
389
|
+
* value does */
|
390
|
+
value = jit_value_create(function, type);
|
391
|
+
return Data_Wrap_Struct(klass, 0, 0, value);
|
392
|
+
}
|
393
|
+
|
394
|
+
static VALUE coerce_to_jit(VALUE function, VALUE type_v, VALUE value_v);
|
395
|
+
|
396
|
+
/*
|
397
|
+
* call-seq:
|
398
|
+
* value = function.value(type)
|
399
|
+
* value = function.value(type, initial_value)
|
400
|
+
*
|
401
|
+
* Create a value (placeholder/variable) with the given type.
|
402
|
+
*/
|
403
|
+
static VALUE function_value(int argc, VALUE * argv, VALUE self)
|
404
|
+
{
|
405
|
+
VALUE type_v = Qnil;
|
406
|
+
VALUE initial_value_v = Qnil;
|
407
|
+
|
408
|
+
VALUE new_value = Qnil;
|
409
|
+
|
410
|
+
rb_scan_args(argc, argv, "11", &type_v, &initial_value_v);
|
411
|
+
|
412
|
+
new_value = function_value_klass(self, type_v, rb_cValue);
|
413
|
+
|
414
|
+
if(argc > 1)
|
415
|
+
{
|
416
|
+
function_insn_store(
|
417
|
+
self,
|
418
|
+
new_value,
|
419
|
+
coerce_to_jit(self, type_v, initial_value_v));
|
420
|
+
}
|
421
|
+
|
422
|
+
return new_value;
|
423
|
+
}
|
424
|
+
|
425
|
+
static jit_value_t create_const(jit_function_t function, jit_type_t type, VALUE constant)
|
426
|
+
{
|
427
|
+
jit_constant_t c;
|
428
|
+
int kind = jit_type_get_kind(type);
|
429
|
+
|
430
|
+
switch(kind)
|
431
|
+
{
|
432
|
+
case JIT_TYPE_INT:
|
433
|
+
{
|
434
|
+
c.type = type;
|
435
|
+
c.un.int_value = NUM2INT(constant);
|
436
|
+
break;
|
437
|
+
}
|
438
|
+
|
439
|
+
case JIT_TYPE_UINT:
|
440
|
+
{
|
441
|
+
c.type = type;
|
442
|
+
c.un.int_value = NUM2UINT(constant);
|
443
|
+
break;
|
444
|
+
}
|
445
|
+
|
446
|
+
case JIT_TYPE_FLOAT32:
|
447
|
+
{
|
448
|
+
c.type = type;
|
449
|
+
c.un.float32_value = NUM2DBL(constant);
|
450
|
+
break;
|
451
|
+
}
|
452
|
+
|
453
|
+
case JIT_TYPE_FLOAT64:
|
454
|
+
{
|
455
|
+
c.type = type;
|
456
|
+
c.un.float64_value = NUM2DBL(constant);
|
457
|
+
break;
|
458
|
+
}
|
459
|
+
|
460
|
+
case JIT_TYPE_PTR:
|
461
|
+
{
|
462
|
+
c.type = type;
|
463
|
+
c.un.ptr_value = (void *)NUM2ULONG(constant);
|
464
|
+
break;
|
465
|
+
}
|
466
|
+
|
467
|
+
case JIT_TYPE_FIRST_TAGGED + RJT_OBJECT:
|
468
|
+
{
|
469
|
+
VALUE value_objects = (VALUE)jit_function_get_meta(function, RJT_VALUE_OBJECTS);
|
470
|
+
|
471
|
+
c.type = type;
|
472
|
+
SET_CONSTANT_VALUE(c, constant);
|
473
|
+
|
474
|
+
/* Make sure the object gets marked as long as the function is
|
475
|
+
* around */
|
476
|
+
rb_ary_push(value_objects, constant);
|
477
|
+
break;
|
478
|
+
}
|
479
|
+
|
480
|
+
case JIT_TYPE_FIRST_TAGGED + RJT_ID:
|
481
|
+
{
|
482
|
+
c.type = type;
|
483
|
+
SET_CONSTANT_ID(c, SYM2ID(constant));
|
484
|
+
break;
|
485
|
+
}
|
486
|
+
|
487
|
+
case JIT_TYPE_FIRST_TAGGED + RJT_FUNCTION_PTR:
|
488
|
+
{
|
489
|
+
c.type = type;
|
490
|
+
SET_FUNCTION_POINTER_VALUE(
|
491
|
+
c,
|
492
|
+
(Void_Function_Ptr)NUM2ULONG(rb_to_int(constant)));
|
493
|
+
break;
|
494
|
+
}
|
495
|
+
|
496
|
+
default:
|
497
|
+
rb_raise(rb_eTypeError, "Unsupported type");
|
498
|
+
}
|
499
|
+
|
500
|
+
return jit_value_create_constant(function, &c);
|
501
|
+
}
|
502
|
+
|
503
|
+
/*
|
504
|
+
* call-seq:
|
505
|
+
* value = function.const(type, constant_value)
|
506
|
+
*
|
507
|
+
* Create a constant value with the given type.
|
508
|
+
*/
|
509
|
+
static VALUE function_const(VALUE self, VALUE type_v, VALUE constant)
|
510
|
+
{
|
511
|
+
jit_function_t function;
|
512
|
+
jit_type_t type;
|
513
|
+
jit_value_t value;
|
514
|
+
|
515
|
+
Data_Get_Struct(self, struct _jit_function, function);
|
516
|
+
|
517
|
+
check_type("type", rb_cType, type_v);
|
518
|
+
Data_Get_Struct(type_v, struct _jit_type, type);
|
519
|
+
|
520
|
+
value = create_const(function, type, constant);
|
521
|
+
return Data_Wrap_Struct(rb_cValue, 0, 0, value);
|
522
|
+
}
|
523
|
+
|
524
|
+
static VALUE coerce_to_jit(VALUE function, VALUE type_v, VALUE value_v)
|
525
|
+
{
|
526
|
+
if(rb_obj_is_kind_of(value_v, rb_cValue))
|
527
|
+
{
|
528
|
+
return value_v;
|
529
|
+
}
|
530
|
+
else
|
531
|
+
{
|
532
|
+
return function_const(function, type_v, value_v);
|
533
|
+
}
|
534
|
+
}
|
535
|
+
|
536
|
+
static void convert_call_args(jit_function_t function, jit_value_t * args, VALUE args_v, jit_type_t signature)
|
537
|
+
{
|
538
|
+
int j;
|
539
|
+
|
540
|
+
for(j = 0; j < RARRAY(args_v)->len; ++j)
|
541
|
+
{
|
542
|
+
VALUE value = RARRAY(args_v)->ptr[j];
|
543
|
+
jit_value_t arg;
|
544
|
+
|
545
|
+
jit_type_t type = jit_type_get_param(signature, j);
|
546
|
+
if(!type)
|
547
|
+
{
|
548
|
+
rb_raise(rb_eArgError, "Type missing for param %d", j);
|
549
|
+
}
|
550
|
+
|
551
|
+
if(rb_obj_is_kind_of(value, rb_cValue))
|
552
|
+
{
|
553
|
+
Data_Get_Struct(value, struct _jit_value, arg);
|
554
|
+
if(!arg)
|
555
|
+
{
|
556
|
+
rb_raise(rb_eArgError, "Argument %d is invalid", j);
|
557
|
+
}
|
558
|
+
args[j] = arg;
|
559
|
+
}
|
560
|
+
else
|
561
|
+
{
|
562
|
+
args[j] = create_const(function, type, value);
|
563
|
+
}
|
564
|
+
}
|
565
|
+
}
|
566
|
+
|
567
|
+
/*
|
568
|
+
* call-seq:
|
569
|
+
* value = function.call(name, called_function, flags, [arg1 [, ... ]])
|
570
|
+
*
|
571
|
+
* Generate an instruction to call the specified function.
|
572
|
+
*/
|
573
|
+
static VALUE function_insn_call(int argc, VALUE * argv, VALUE self)
|
574
|
+
{
|
575
|
+
jit_function_t function;
|
576
|
+
|
577
|
+
VALUE name_v;
|
578
|
+
VALUE called_function_v;
|
579
|
+
VALUE args_v;
|
580
|
+
VALUE flags_v = Qnil;
|
581
|
+
|
582
|
+
char const * name;
|
583
|
+
jit_function_t called_function;
|
584
|
+
jit_type_t signature;
|
585
|
+
jit_value_t * args;
|
586
|
+
jit_value_t retval;
|
587
|
+
int flags;
|
588
|
+
size_t num_args;
|
589
|
+
|
590
|
+
rb_scan_args(argc, argv, "3*", &name_v, &called_function_v, &flags_v, &args_v);
|
591
|
+
|
592
|
+
Data_Get_Struct(self, struct _jit_function, function);
|
593
|
+
|
594
|
+
name = STR2CSTR(name_v);
|
595
|
+
|
596
|
+
check_type("called function", rb_cFunction, called_function_v);
|
597
|
+
Data_Get_Struct(called_function_v, struct _jit_function, called_function);
|
598
|
+
|
599
|
+
num_args = RARRAY(args_v)->len;
|
600
|
+
args = ALLOCA_N(jit_value_t, num_args);
|
601
|
+
|
602
|
+
signature = jit_function_get_signature(function);
|
603
|
+
convert_call_args(function, args, args_v, signature);
|
604
|
+
|
605
|
+
flags = NUM2INT(flags_v);
|
606
|
+
|
607
|
+
retval = jit_insn_call(
|
608
|
+
function, name, called_function, 0, args, num_args, flags);
|
609
|
+
return Data_Wrap_Struct(rb_cValue, 0, 0, retval);
|
610
|
+
}
|
611
|
+
|
612
|
+
/*
|
613
|
+
* call-seq:
|
614
|
+
* value = function.call(name, flags, [arg1 [, ... ]])
|
615
|
+
*
|
616
|
+
* Generate an instruction to call a native function.
|
617
|
+
*/
|
618
|
+
static VALUE function_insn_call_native(int argc, VALUE * argv, VALUE self)
|
619
|
+
{
|
620
|
+
jit_function_t function;
|
621
|
+
|
622
|
+
VALUE name_v;
|
623
|
+
VALUE args_v;
|
624
|
+
VALUE function_ptr_v;
|
625
|
+
VALUE signature_v;
|
626
|
+
VALUE flags_v;
|
627
|
+
|
628
|
+
char const * name;
|
629
|
+
jit_value_t * args;
|
630
|
+
jit_value_t retval;
|
631
|
+
void * function_ptr;
|
632
|
+
jit_type_t signature;
|
633
|
+
int flags;
|
634
|
+
size_t num_args;
|
635
|
+
|
636
|
+
rb_scan_args(argc, argv, "4*", &name_v, &function_ptr_v, &signature_v, &flags_v, &args_v);
|
637
|
+
|
638
|
+
Data_Get_Struct(self, struct _jit_function, function);
|
639
|
+
|
640
|
+
if(SYMBOL_P(name_v))
|
641
|
+
{
|
642
|
+
name = rb_id2name(SYM2ID(name_v));
|
643
|
+
}
|
644
|
+
else
|
645
|
+
{
|
646
|
+
name = StringValuePtr(name_v);
|
647
|
+
}
|
648
|
+
|
649
|
+
function_ptr = (void *)NUM2ULONG(function_ptr_v);
|
650
|
+
|
651
|
+
Data_Get_Struct(signature_v, struct _jit_type, signature);
|
652
|
+
|
653
|
+
num_args = RARRAY(args_v)->len;
|
654
|
+
args = ALLOCA_N(jit_value_t, num_args);
|
655
|
+
|
656
|
+
if(num_args != jit_type_num_params(signature))
|
657
|
+
{
|
658
|
+
rb_raise(
|
659
|
+
rb_eArgError,
|
660
|
+
"Wrong number of arguments passed for %s (expecting %d but got %d)",
|
661
|
+
name,
|
662
|
+
jit_type_num_params(signature),
|
663
|
+
num_args);
|
664
|
+
}
|
665
|
+
|
666
|
+
convert_call_args(function, args, args_v, signature);
|
667
|
+
|
668
|
+
flags = NUM2INT(flags_v);
|
669
|
+
|
670
|
+
retval = jit_insn_call_native(
|
671
|
+
function, name, function_ptr, signature, args, num_args, flags);
|
672
|
+
return Data_Wrap_Struct(rb_cValue, 0, 0, retval);
|
673
|
+
}
|
674
|
+
|
675
|
+
/*
|
676
|
+
* call-seq:
|
677
|
+
* function.insn_return()
|
678
|
+
* function.insn_return(value)
|
679
|
+
*
|
680
|
+
* Emit an instruction to return from the function. If value is
|
681
|
+
* specified, return the given value, otherwise return void.
|
682
|
+
*/
|
683
|
+
static VALUE function_insn_return(int argc, VALUE * argv, VALUE self)
|
684
|
+
{
|
685
|
+
jit_function_t function;
|
686
|
+
jit_value_t value = 0;
|
687
|
+
VALUE value_v = Qnil;
|
688
|
+
|
689
|
+
rb_scan_args(argc, argv, "01", &value_v);
|
690
|
+
|
691
|
+
if(value_v != Qnil)
|
692
|
+
{
|
693
|
+
Data_Get_Struct(value_v, struct _jit_value, value);
|
694
|
+
}
|
695
|
+
|
696
|
+
Data_Get_Struct(self, struct _jit_function, function);
|
697
|
+
jit_insn_return(function, value);
|
698
|
+
|
699
|
+
return Qnil;
|
700
|
+
}
|
701
|
+
|
702
|
+
/*
|
703
|
+
* call-seq:
|
704
|
+
* function.apply(arg1 [, arg2 [, ... ]])
|
705
|
+
*
|
706
|
+
* Call a compiled function. Each argument passed in will be converted
|
707
|
+
* to the type specified by the function's signature.
|
708
|
+
*
|
709
|
+
* If the function's signature is Type::RUBY_VARARG_SIGNATURE, then the
|
710
|
+
* arguments will be passed in with the first parameter the count of the
|
711
|
+
* number of arguments, the second parameter a pointer to an array
|
712
|
+
* containing the second through the last argument, and the third
|
713
|
+
* parameter the explicit self (that is, the first argument passed to
|
714
|
+
* apply).
|
715
|
+
*/
|
716
|
+
static VALUE function_apply(int argc, VALUE * argv, VALUE self)
|
717
|
+
{
|
718
|
+
jit_function_t function;
|
719
|
+
jit_type_t signature;
|
720
|
+
int j, n;
|
721
|
+
void * * args;
|
722
|
+
char * arg_data;
|
723
|
+
int signature_tag;
|
724
|
+
|
725
|
+
Data_Get_Struct(self, struct _jit_function, function);
|
726
|
+
signature = jit_function_get_signature(function);
|
727
|
+
n = jit_type_num_params(signature);
|
728
|
+
|
729
|
+
/* void pointers to each of the arguments */
|
730
|
+
args = ALLOCA_N(void *, n);
|
731
|
+
|
732
|
+
/* the actual data */
|
733
|
+
/* TODO: we need to allocate the proper size (but 8 bytes per arg
|
734
|
+
* should be sufficient for now) */
|
735
|
+
arg_data = (char *)ALLOCA_N(char, 8 * n);
|
736
|
+
|
737
|
+
signature_tag = (int)jit_function_get_meta(function, RJT_TAG_FOR_SIGNATURE);
|
738
|
+
if(signature_tag == JIT_TYPE_FIRST_TAGGED + RJT_RUBY_VARARG_SIGNATURE)
|
739
|
+
{
|
740
|
+
jit_VALUE result;
|
741
|
+
int f_argc = argc - 1;
|
742
|
+
VALUE f_self = *(VALUE *)argv;
|
743
|
+
VALUE * f_argv = ((VALUE *)argv) + 1;
|
744
|
+
void * f_args[3];
|
745
|
+
f_args[0] = &f_argc;
|
746
|
+
f_args[1] = &f_argv;
|
747
|
+
f_args[2] = &f_self;
|
748
|
+
jit_function_apply(function, f_args, &result);
|
749
|
+
return result;
|
750
|
+
}
|
751
|
+
|
752
|
+
if(argc != n)
|
753
|
+
{
|
754
|
+
rb_raise(
|
755
|
+
rb_eArgError,
|
756
|
+
"Wrong number of arguments (expected %d but got %d)",
|
757
|
+
n,
|
758
|
+
argc);
|
759
|
+
}
|
760
|
+
|
761
|
+
for(j = 0; j < n; ++j)
|
762
|
+
{
|
763
|
+
jit_type_t arg_type = jit_type_get_param(signature, j);
|
764
|
+
int kind = jit_type_get_kind(arg_type);
|
765
|
+
switch(kind)
|
766
|
+
{
|
767
|
+
case JIT_TYPE_INT:
|
768
|
+
{
|
769
|
+
*(int *)arg_data = NUM2INT(argv[j]);
|
770
|
+
args[j] = (int *)arg_data;
|
771
|
+
arg_data += sizeof(int);
|
772
|
+
break;
|
773
|
+
}
|
774
|
+
|
775
|
+
case JIT_TYPE_UINT:
|
776
|
+
{
|
777
|
+
*(int *)arg_data = NUM2UINT(argv[j]);
|
778
|
+
args[j] = (int *)arg_data;
|
779
|
+
arg_data += sizeof(int);
|
780
|
+
break;
|
781
|
+
}
|
782
|
+
|
783
|
+
case JIT_TYPE_FIRST_TAGGED + RJT_OBJECT:
|
784
|
+
{
|
785
|
+
*(VALUE *)arg_data = argv[j];
|
786
|
+
args[j] = (VALUE *)arg_data;
|
787
|
+
arg_data += sizeof(VALUE);
|
788
|
+
break;
|
789
|
+
}
|
790
|
+
|
791
|
+
case JIT_TYPE_FIRST_TAGGED + RJT_ID:
|
792
|
+
{
|
793
|
+
*(ID *)arg_data = SYM2ID(argv[j]);
|
794
|
+
args[j] = (ID *)arg_data;
|
795
|
+
arg_data += sizeof(ID);
|
796
|
+
break;
|
797
|
+
}
|
798
|
+
|
799
|
+
case JIT_TYPE_FIRST_TAGGED + RJT_FUNCTION_PTR:
|
800
|
+
{
|
801
|
+
*(Void_Function_Ptr *)arg_data =
|
802
|
+
(Void_Function_Ptr)NUM2ULONG(rb_to_int(argv[j]));
|
803
|
+
args[j] = (Void_Function_Ptr *)(arg_data);
|
804
|
+
arg_data += sizeof(Void_Function_Ptr);
|
805
|
+
break;
|
806
|
+
}
|
807
|
+
|
808
|
+
default:
|
809
|
+
rb_raise(rb_eTypeError, "Unsupported type %d", kind);
|
810
|
+
}
|
811
|
+
}
|
812
|
+
|
813
|
+
{
|
814
|
+
jit_type_t return_type = jit_type_get_return(signature);
|
815
|
+
int return_kind = jit_type_get_kind(return_type);
|
816
|
+
switch(return_kind)
|
817
|
+
{
|
818
|
+
case JIT_TYPE_INT:
|
819
|
+
{
|
820
|
+
jit_int result;
|
821
|
+
jit_function_apply(function, args, &result);
|
822
|
+
return INT2NUM(result);
|
823
|
+
}
|
824
|
+
|
825
|
+
case JIT_TYPE_FLOAT32:
|
826
|
+
{
|
827
|
+
jit_float32 result;
|
828
|
+
jit_function_apply(function, args, &result);
|
829
|
+
return rb_float_new(result);
|
830
|
+
}
|
831
|
+
|
832
|
+
case JIT_TYPE_FLOAT64:
|
833
|
+
{
|
834
|
+
jit_float64 result;
|
835
|
+
jit_function_apply(function, args, &result);
|
836
|
+
return rb_float_new(result);
|
837
|
+
}
|
838
|
+
|
839
|
+
case JIT_TYPE_FIRST_TAGGED + RJT_OBJECT:
|
840
|
+
{
|
841
|
+
jit_VALUE result;
|
842
|
+
jit_function_apply(function, args, &result);
|
843
|
+
return result;
|
844
|
+
}
|
845
|
+
|
846
|
+
case JIT_TYPE_FIRST_TAGGED + RJT_ID:
|
847
|
+
{
|
848
|
+
jit_ID result;
|
849
|
+
jit_function_apply(function, args, &result);
|
850
|
+
return ID2SYM(result);
|
851
|
+
}
|
852
|
+
|
853
|
+
default:
|
854
|
+
rb_raise(rb_eTypeError, "Unsupported return type %d", return_kind);
|
855
|
+
}
|
856
|
+
}
|
857
|
+
}
|
858
|
+
|
859
|
+
/*
|
860
|
+
* call-seq:
|
861
|
+
* level = function.optimization_level()
|
862
|
+
*
|
863
|
+
* Get the optimization level for a function.
|
864
|
+
*/
|
865
|
+
static VALUE function_optimization_level(VALUE self)
|
866
|
+
{
|
867
|
+
jit_function_t function;
|
868
|
+
Data_Get_Struct(self, struct _jit_function, function);
|
869
|
+
return INT2NUM(jit_function_get_optimization_level(function));
|
870
|
+
}
|
871
|
+
|
872
|
+
/*
|
873
|
+
* call-seq:
|
874
|
+
* function.optimization_level = level
|
875
|
+
*
|
876
|
+
* Set the optimization level for a function.
|
877
|
+
*/
|
878
|
+
static VALUE function_set_optimization_level(VALUE self, VALUE level)
|
879
|
+
{
|
880
|
+
jit_function_t function;
|
881
|
+
Data_Get_Struct(self, struct _jit_function, function);
|
882
|
+
jit_function_set_optimization_level(function, NUM2INT(level));
|
883
|
+
return level;
|
884
|
+
}
|
885
|
+
|
886
|
+
/*
|
887
|
+
* call-seq:
|
888
|
+
* level = function.max_optimization_level()
|
889
|
+
*
|
890
|
+
* Get the maximum optimization level (which should be the same for any
|
891
|
+
* function).
|
892
|
+
*/
|
893
|
+
static VALUE function_max_optimization_level(VALUE klass)
|
894
|
+
{
|
895
|
+
return INT2NUM(jit_function_get_max_optimization_level());
|
896
|
+
}
|
897
|
+
|
898
|
+
/*
|
899
|
+
* call-seq:
|
900
|
+
* str = function.dump()
|
901
|
+
*
|
902
|
+
* Dump the instructions in a function to a string.
|
903
|
+
*/
|
904
|
+
static VALUE function_dump(VALUE self)
|
905
|
+
{
|
906
|
+
#ifdef HAVE_FMEMOPEN
|
907
|
+
jit_function_t function;
|
908
|
+
char buf[16*1024]; /* TODO: big enough? */
|
909
|
+
FILE * fp = fmemopen(buf, sizeof(buf), "w");
|
910
|
+
Data_Get_Struct(self, struct _jit_function, function);
|
911
|
+
jit_dump_function(fp, function, 0);
|
912
|
+
fclose(fp);
|
913
|
+
return rb_str_new2(buf);
|
914
|
+
#else
|
915
|
+
rb_raise(rb_eNotImpError, "Not implemented: missing fmemopen");
|
916
|
+
#endif
|
917
|
+
}
|
918
|
+
|
919
|
+
/*
|
920
|
+
* call-seq:
|
921
|
+
* ptr = function.to_closure()
|
922
|
+
*
|
923
|
+
* Return a pointer to a closure for a function. This pointer can be
|
924
|
+
* passed into other functions as a function pointer.
|
925
|
+
*/
|
926
|
+
static VALUE function_to_closure(VALUE self)
|
927
|
+
{
|
928
|
+
jit_function_t function;
|
929
|
+
struct Closure * closure;
|
930
|
+
VALUE closure_v = Data_Make_Struct(
|
931
|
+
rb_cClosure, struct Closure, mark_closure, free, closure);
|
932
|
+
Data_Get_Struct(self, struct _jit_function, function);
|
933
|
+
closure->function = self;
|
934
|
+
closure->function_ptr =
|
935
|
+
(Void_Function_Ptr)jit_function_to_closure(function);
|
936
|
+
return closure_v;
|
937
|
+
}
|
938
|
+
|
939
|
+
/*
|
940
|
+
* call-seq:
|
941
|
+
* context = function.context()
|
942
|
+
*
|
943
|
+
* Get a function's context.
|
944
|
+
*/
|
945
|
+
static VALUE function_get_context(VALUE self)
|
946
|
+
{
|
947
|
+
jit_function_t function;
|
948
|
+
Data_Get_Struct(self, struct _jit_function, function);
|
949
|
+
return (VALUE)jit_function_get_meta(function, RJT_CONTEXT);
|
950
|
+
}
|
951
|
+
|
952
|
+
/*
|
953
|
+
* call-seq:
|
954
|
+
* is_compiled = function.compiled?
|
955
|
+
*
|
956
|
+
* Determine whether a function is compiled.
|
957
|
+
*/
|
958
|
+
static VALUE function_is_compiled(VALUE self)
|
959
|
+
{
|
960
|
+
jit_function_t function;
|
961
|
+
Data_Get_Struct(self, struct _jit_function, function);
|
962
|
+
return jit_function_is_compiled(function) ? Qtrue : Qfalse;
|
963
|
+
}
|
964
|
+
|
965
|
+
/* ---------------------------------------------------------------------------
|
966
|
+
* Type
|
967
|
+
* ---------------------------------------------------------------------------
|
968
|
+
*/
|
969
|
+
|
970
|
+
/* This function does not increment the reference count. It is assumed
|
971
|
+
* that the caller will increment the reference count and that the newly
|
972
|
+
* wrapped object will take ownership. */
|
973
|
+
static VALUE wrap_type_with_klass(jit_type_t type, VALUE klass)
|
974
|
+
{
|
975
|
+
return Data_Wrap_Struct(klass, 0, jit_type_free, type);
|
976
|
+
}
|
977
|
+
|
978
|
+
static VALUE wrap_type(jit_type_t type)
|
979
|
+
{
|
980
|
+
return wrap_type_with_klass(type, rb_cType);
|
981
|
+
}
|
982
|
+
|
983
|
+
/*
|
984
|
+
* call-seq:
|
985
|
+
* type = Type.create_signature(abi, return_type, array_of_param_types)
|
986
|
+
*
|
987
|
+
* Create a new signature.
|
988
|
+
*/
|
989
|
+
static VALUE type_s_create_signature(
|
990
|
+
VALUE klass, VALUE abi_v, VALUE return_type_v, VALUE params_v)
|
991
|
+
{
|
992
|
+
jit_abi_t abi = NUM2INT(abi_v);
|
993
|
+
jit_type_t return_type;
|
994
|
+
jit_type_t * params;
|
995
|
+
jit_type_t signature;
|
996
|
+
int j;
|
997
|
+
int len;
|
998
|
+
|
999
|
+
check_type("return type", rb_cType, return_type_v);
|
1000
|
+
|
1001
|
+
Data_Get_Struct(return_type_v, struct _jit_type, return_type);
|
1002
|
+
|
1003
|
+
Check_Type(params_v, T_ARRAY);
|
1004
|
+
len = RARRAY(params_v)->len;
|
1005
|
+
params = ALLOCA_N(jit_type_t, len);
|
1006
|
+
for(j = 0; j < len; ++j)
|
1007
|
+
{
|
1008
|
+
VALUE param = RARRAY(params_v)->ptr[j];
|
1009
|
+
check_type("param", rb_cType, param);
|
1010
|
+
Data_Get_Struct(param, struct _jit_type, params[j]);
|
1011
|
+
}
|
1012
|
+
|
1013
|
+
signature = jit_type_create_signature(abi, return_type, params, len, 1);
|
1014
|
+
return wrap_type(signature);
|
1015
|
+
}
|
1016
|
+
|
1017
|
+
/*
|
1018
|
+
* call-seq:
|
1019
|
+
* type = Type.create_struct(array_of_field_types)
|
1020
|
+
*
|
1021
|
+
* Create a new struct type.
|
1022
|
+
*/
|
1023
|
+
static VALUE type_s_create_struct(
|
1024
|
+
VALUE klass, VALUE fields_v)
|
1025
|
+
{
|
1026
|
+
jit_type_t * fields;
|
1027
|
+
jit_type_t struct_type;
|
1028
|
+
int len;
|
1029
|
+
int j;
|
1030
|
+
|
1031
|
+
Check_Type(fields_v, T_ARRAY);
|
1032
|
+
len = RARRAY(fields_v)->len;
|
1033
|
+
fields = ALLOCA_N(jit_type_t, len);
|
1034
|
+
for(j = 0; j < len; ++j)
|
1035
|
+
{
|
1036
|
+
VALUE field = RARRAY(fields_v)->ptr[j];
|
1037
|
+
check_type("field", rb_cType, field);
|
1038
|
+
Data_Get_Struct(field, struct _jit_type, fields[j]);
|
1039
|
+
}
|
1040
|
+
|
1041
|
+
struct_type = jit_type_create_struct(fields, RARRAY(fields_v)->len, 1);
|
1042
|
+
return wrap_type_with_klass(struct_type, klass);
|
1043
|
+
}
|
1044
|
+
|
1045
|
+
/*
|
1046
|
+
* call-seq:
|
1047
|
+
* type = Type.create_pointer(pointed_to_type)
|
1048
|
+
*
|
1049
|
+
* Create a new pointer type, pointing to the given type.
|
1050
|
+
*/
|
1051
|
+
static VALUE type_s_create_pointer(
|
1052
|
+
VALUE klass, VALUE type_v)
|
1053
|
+
{
|
1054
|
+
jit_type_t type;
|
1055
|
+
jit_type_t pointer_type;
|
1056
|
+
Data_Get_Struct(type_v, struct _jit_type, type);
|
1057
|
+
pointer_type = jit_type_create_pointer(type, 1);
|
1058
|
+
return wrap_type_with_klass(pointer_type, klass);
|
1059
|
+
}
|
1060
|
+
|
1061
|
+
/*
|
1062
|
+
* call-seq:
|
1063
|
+
* offset = struct_type.get_offset(index)
|
1064
|
+
*
|
1065
|
+
* Get the offset of the nth field in a struct.
|
1066
|
+
*/
|
1067
|
+
static VALUE type_get_offset(VALUE self, VALUE field_index_v)
|
1068
|
+
{
|
1069
|
+
int field_index = NUM2INT(field_index_v);
|
1070
|
+
jit_type_t type;
|
1071
|
+
Data_Get_Struct(self, struct _jit_type, type);
|
1072
|
+
return INT2NUM(jit_type_get_offset(type, field_index));
|
1073
|
+
}
|
1074
|
+
|
1075
|
+
/*
|
1076
|
+
* call-seq:
|
1077
|
+
* offset = struct_type.set_offset(index, offset)
|
1078
|
+
*
|
1079
|
+
* Set the offset of the nth field in a struct.
|
1080
|
+
*/
|
1081
|
+
static VALUE type_set_offset(VALUE self, VALUE field_index_v, VALUE offset_v)
|
1082
|
+
{
|
1083
|
+
int field_index = NUM2INT(field_index_v);
|
1084
|
+
int offset = NUM2UINT(offset_v);
|
1085
|
+
jit_type_t type;
|
1086
|
+
Data_Get_Struct(self, struct _jit_type, type);
|
1087
|
+
jit_type_set_offset(type, field_index, offset);
|
1088
|
+
return Qnil;
|
1089
|
+
}
|
1090
|
+
|
1091
|
+
/*
|
1092
|
+
* call-seq:
|
1093
|
+
* offset = struct_type.size
|
1094
|
+
*
|
1095
|
+
* Get the size of a struct or union type.
|
1096
|
+
*/
|
1097
|
+
static VALUE type_size(VALUE self)
|
1098
|
+
{
|
1099
|
+
jit_type_t type;
|
1100
|
+
Data_Get_Struct(self, struct _jit_type, type);
|
1101
|
+
return INT2NUM(jit_type_get_size(type));
|
1102
|
+
}
|
1103
|
+
|
1104
|
+
/* ---------------------------------------------------------------------------
|
1105
|
+
* Value
|
1106
|
+
* ---------------------------------------------------------------------------
|
1107
|
+
*/
|
1108
|
+
|
1109
|
+
static VALUE value_s_new_value(VALUE klass, VALUE function, VALUE type)
|
1110
|
+
{
|
1111
|
+
return function_value_klass(function, type, klass);
|
1112
|
+
}
|
1113
|
+
|
1114
|
+
/*
|
1115
|
+
* call-seq:
|
1116
|
+
* str = value.to_s
|
1117
|
+
*
|
1118
|
+
* Return a string representation of the value.
|
1119
|
+
*/
|
1120
|
+
static VALUE value_to_s(VALUE self)
|
1121
|
+
{
|
1122
|
+
#ifdef HAVE_FMEMOPEN
|
1123
|
+
char buf[1024];
|
1124
|
+
FILE * fp = fmemopen(buf, sizeof(buf), "w");
|
1125
|
+
jit_value_t value;
|
1126
|
+
jit_function_t function;
|
1127
|
+
Data_Get_Struct(self, struct _jit_value, value);
|
1128
|
+
function = jit_value_get_function(value);
|
1129
|
+
jit_dump_value(fp, function, value, 0);
|
1130
|
+
fclose(fp);
|
1131
|
+
return rb_str_new2(buf);
|
1132
|
+
#else
|
1133
|
+
rb_raise(rb_eNotImpError, "Not implemented: missing fmemopen");
|
1134
|
+
#endif
|
1135
|
+
}
|
1136
|
+
|
1137
|
+
/*
|
1138
|
+
* call-seq:
|
1139
|
+
* str = value.inspect
|
1140
|
+
*
|
1141
|
+
* Return a string representation of a value with additional
|
1142
|
+
* information about the value.
|
1143
|
+
*/
|
1144
|
+
static VALUE value_inspect(VALUE self)
|
1145
|
+
{
|
1146
|
+
jit_value_t value;
|
1147
|
+
jit_type_t type;
|
1148
|
+
char const * cname = rb_obj_classname(self);
|
1149
|
+
VALUE args[6];
|
1150
|
+
Data_Get_Struct(self, struct _jit_value, value);
|
1151
|
+
type = jit_value_get_type(value);
|
1152
|
+
args[0] = rb_str_new2("#<%s:0x%x %s ptr=0x%x type=0x%x>");
|
1153
|
+
args[1] = rb_str_new2(cname);
|
1154
|
+
args[2] = ULONG2NUM((unsigned long)self);
|
1155
|
+
args[3] = value_to_s(self);
|
1156
|
+
args[4] = ULONG2NUM((unsigned long)value);
|
1157
|
+
args[5] = ULONG2NUM((unsigned long)type);
|
1158
|
+
return rb_f_sprintf(sizeof(args)/sizeof(args[0]), args);
|
1159
|
+
}
|
1160
|
+
|
1161
|
+
/*
|
1162
|
+
* call-seq:
|
1163
|
+
* is_valid = value.valid?
|
1164
|
+
*
|
1165
|
+
* Determine if a value is valid (non-zero).
|
1166
|
+
*/
|
1167
|
+
static VALUE value_is_valid(VALUE self)
|
1168
|
+
{
|
1169
|
+
jit_value_t value;
|
1170
|
+
Data_Get_Struct(self, struct _jit_value, value);
|
1171
|
+
return (value != 0) ? Qtrue : Qfalse;
|
1172
|
+
}
|
1173
|
+
|
1174
|
+
/*
|
1175
|
+
* call-seq:
|
1176
|
+
* is_temporary = value.temporary?
|
1177
|
+
*
|
1178
|
+
* Determine if a value represents a temporary.
|
1179
|
+
*/
|
1180
|
+
static VALUE value_is_temporary(VALUE self)
|
1181
|
+
{
|
1182
|
+
jit_value_t value;
|
1183
|
+
Data_Get_Struct(self, struct _jit_value, value);
|
1184
|
+
return jit_value_is_temporary(value) ? Qtrue : Qfalse;
|
1185
|
+
}
|
1186
|
+
|
1187
|
+
/*
|
1188
|
+
* call-seq:
|
1189
|
+
* is_local = value.local?
|
1190
|
+
*
|
1191
|
+
* Determine if a value represents a local.
|
1192
|
+
*/
|
1193
|
+
static VALUE value_is_local(VALUE self)
|
1194
|
+
{
|
1195
|
+
jit_value_t value;
|
1196
|
+
Data_Get_Struct(self, struct _jit_value, value);
|
1197
|
+
return jit_value_is_local(value) ? Qtrue : Qfalse;
|
1198
|
+
}
|
1199
|
+
|
1200
|
+
/*
|
1201
|
+
* call-seq:
|
1202
|
+
* is_local = value.constant?
|
1203
|
+
*
|
1204
|
+
* Determine if a value represents a constant.
|
1205
|
+
*/
|
1206
|
+
static VALUE value_is_constant(VALUE self)
|
1207
|
+
{
|
1208
|
+
jit_value_t value;
|
1209
|
+
Data_Get_Struct(self, struct _jit_value, value);
|
1210
|
+
return jit_value_is_constant(value) ? Qtrue : Qfalse;
|
1211
|
+
}
|
1212
|
+
|
1213
|
+
/*
|
1214
|
+
* call-seq:
|
1215
|
+
* is_volatile = value.volatile?
|
1216
|
+
*
|
1217
|
+
* Determine if a value is volatile (that is, the contents must be
|
1218
|
+
* reloaded from memory each time it is used).
|
1219
|
+
*/
|
1220
|
+
static VALUE value_is_volatile(VALUE self)
|
1221
|
+
{
|
1222
|
+
jit_value_t value;
|
1223
|
+
Data_Get_Struct(self, struct _jit_value, value);
|
1224
|
+
return jit_value_is_volatile(value) ? Qtrue : Qfalse;
|
1225
|
+
}
|
1226
|
+
|
1227
|
+
/*
|
1228
|
+
* call-seq:
|
1229
|
+
* value.volatile = is_volatile
|
1230
|
+
*
|
1231
|
+
* Make a value volatile (that is, ensure that its contents are reloaded
|
1232
|
+
* from memory each time it is used).
|
1233
|
+
*/
|
1234
|
+
static VALUE value_set_volatile(VALUE self)
|
1235
|
+
{
|
1236
|
+
jit_value_t value;
|
1237
|
+
Data_Get_Struct(self, struct _jit_value, value);
|
1238
|
+
jit_value_set_volatile(value);
|
1239
|
+
return Qnil;
|
1240
|
+
}
|
1241
|
+
|
1242
|
+
/*
|
1243
|
+
* call-seq:
|
1244
|
+
* is_addressable = value.addressable?
|
1245
|
+
*
|
1246
|
+
* Determine if a value is addressable.
|
1247
|
+
*/
|
1248
|
+
static VALUE value_is_addressable(VALUE self)
|
1249
|
+
{
|
1250
|
+
jit_value_t value;
|
1251
|
+
Data_Get_Struct(self, struct _jit_value, value);
|
1252
|
+
return jit_value_is_addressable(value) ? Qtrue : Qfalse;
|
1253
|
+
}
|
1254
|
+
|
1255
|
+
/*
|
1256
|
+
* call-seq:
|
1257
|
+
* value.addressable = is_addressable
|
1258
|
+
*
|
1259
|
+
* Make a value addressable.
|
1260
|
+
*/
|
1261
|
+
static VALUE value_set_addressable(VALUE self)
|
1262
|
+
{
|
1263
|
+
jit_value_t value;
|
1264
|
+
Data_Get_Struct(self, struct _jit_value, value);
|
1265
|
+
jit_value_set_addressable(value);
|
1266
|
+
return Qnil;
|
1267
|
+
}
|
1268
|
+
|
1269
|
+
/*
|
1270
|
+
* call-seq:
|
1271
|
+
* function = value.function()
|
1272
|
+
*
|
1273
|
+
* Get a value's function.
|
1274
|
+
*/
|
1275
|
+
static VALUE value_function(VALUE self)
|
1276
|
+
{
|
1277
|
+
jit_value_t value;
|
1278
|
+
jit_function_t function;
|
1279
|
+
Data_Get_Struct(self, struct _jit_value, value);
|
1280
|
+
function = jit_value_get_function(value);
|
1281
|
+
return Data_Wrap_Struct(rb_cFunction, mark_function, 0, function);
|
1282
|
+
}
|
1283
|
+
|
1284
|
+
/*
|
1285
|
+
* call-seq:
|
1286
|
+
* function = value.type()
|
1287
|
+
*
|
1288
|
+
* Get a value's type.
|
1289
|
+
*/
|
1290
|
+
static VALUE value_type(VALUE self)
|
1291
|
+
{
|
1292
|
+
jit_value_t value;
|
1293
|
+
jit_type_t type;
|
1294
|
+
Data_Get_Struct(self, struct _jit_value, value);
|
1295
|
+
type = jit_value_get_type(value);
|
1296
|
+
return wrap_type(type);
|
1297
|
+
}
|
1298
|
+
|
1299
|
+
/*
|
1300
|
+
* call-seq:
|
1301
|
+
* value1, value2 = value1.coerce(value2)
|
1302
|
+
*
|
1303
|
+
* If the given value is a JIT::Value, return an +[ self, value ]+,
|
1304
|
+
* otherwise coerce the value to the same type as self and return
|
1305
|
+
* +[ self, coerced_value ]+.
|
1306
|
+
*/
|
1307
|
+
static VALUE value_coerce(VALUE self, VALUE value)
|
1308
|
+
{
|
1309
|
+
return rb_assoc_new(
|
1310
|
+
self,
|
1311
|
+
coerce_to_jit(
|
1312
|
+
value_function(self),
|
1313
|
+
value_type(self),
|
1314
|
+
value));
|
1315
|
+
}
|
1316
|
+
|
1317
|
+
/* ---------------------------------------------------------------------------
|
1318
|
+
* Label
|
1319
|
+
* ---------------------------------------------------------------------------
|
1320
|
+
*/
|
1321
|
+
|
1322
|
+
/*
|
1323
|
+
* call-seq:
|
1324
|
+
* label = Label.new
|
1325
|
+
*
|
1326
|
+
* Create a new label.
|
1327
|
+
*/
|
1328
|
+
static VALUE label_s_new(VALUE klass)
|
1329
|
+
{
|
1330
|
+
jit_label_t * label;
|
1331
|
+
VALUE labelval = Data_Make_Struct(rb_cLabel, jit_label_t, 0, xfree, label);
|
1332
|
+
*label = jit_label_undefined;
|
1333
|
+
return labelval;
|
1334
|
+
}
|
1335
|
+
|
1336
|
+
/* ---------------------------------------------------------------------------
|
1337
|
+
* Module
|
1338
|
+
* ---------------------------------------------------------------------------
|
1339
|
+
*/
|
1340
|
+
|
1341
|
+
/*
|
1342
|
+
* call-seq:
|
1343
|
+
* module.define_jit_method(name, function)
|
1344
|
+
*
|
1345
|
+
* Use a Function to define an instance method on a module. The
|
1346
|
+
* function should have one of two signatures:
|
1347
|
+
*
|
1348
|
+
* * The first parameter to the function should be an OBJECT that
|
1349
|
+
* represents the self parameter and the rest of the parameters, or
|
1350
|
+
*
|
1351
|
+
* * The function's signature should be Type::RUBY_VARARG_SIGNATURE.
|
1352
|
+
*/
|
1353
|
+
static VALUE module_define_jit_method(VALUE klass, VALUE name_v, VALUE function_v)
|
1354
|
+
{
|
1355
|
+
char const * name;
|
1356
|
+
jit_function_t function;
|
1357
|
+
jit_type_t signature;
|
1358
|
+
int signature_tag;
|
1359
|
+
int arity;
|
1360
|
+
VALUE closure_v;
|
1361
|
+
struct Closure * closure;
|
1362
|
+
|
1363
|
+
if(SYMBOL_P(name_v))
|
1364
|
+
{
|
1365
|
+
name = rb_id2name(SYM2ID(name_v));
|
1366
|
+
}
|
1367
|
+
else
|
1368
|
+
{
|
1369
|
+
name = STR2CSTR(name_v);
|
1370
|
+
}
|
1371
|
+
|
1372
|
+
Data_Get_Struct(function_v, struct _jit_function, function);
|
1373
|
+
|
1374
|
+
signature = jit_function_get_signature(function);
|
1375
|
+
signature_tag = (int)jit_function_get_meta(function, RJT_TAG_FOR_SIGNATURE);
|
1376
|
+
if(signature_tag == JIT_TYPE_FIRST_TAGGED + RJT_RUBY_VARARG_SIGNATURE)
|
1377
|
+
{
|
1378
|
+
arity = -1;
|
1379
|
+
}
|
1380
|
+
else
|
1381
|
+
{
|
1382
|
+
/* TODO: check the types to make sure they are OBJECT */
|
1383
|
+
arity = jit_type_num_params(signature) - 1;
|
1384
|
+
}
|
1385
|
+
|
1386
|
+
closure_v = function_to_closure(function_v);
|
1387
|
+
Data_Get_Struct(closure_v, struct Closure, closure);
|
1388
|
+
define_method_with_data(
|
1389
|
+
klass, rb_intern(name), RUBY_METHOD_FUNC(closure->function_ptr),
|
1390
|
+
arity, closure_v);
|
1391
|
+
return Qnil;
|
1392
|
+
}
|
1393
|
+
|
1394
|
+
/* ---------------------------------------------------------------------------
|
1395
|
+
* Init
|
1396
|
+
* ---------------------------------------------------------------------------
|
1397
|
+
*/
|
1398
|
+
|
1399
|
+
void Init_jit()
|
1400
|
+
{
|
1401
|
+
jit_init();
|
1402
|
+
|
1403
|
+
rb_mJIT = rb_define_module("JIT");
|
1404
|
+
|
1405
|
+
rb_cContext = rb_define_class_under(rb_mJIT, "Context", rb_cObject);
|
1406
|
+
rb_define_singleton_method(rb_cContext, "new", context_s_new, 0);
|
1407
|
+
rb_define_method(rb_cContext, "build", context_build, 0);
|
1408
|
+
rb_define_singleton_method(rb_cContext, "build", context_s_build, 0);
|
1409
|
+
|
1410
|
+
rb_cClosure = rb_define_class_under(rb_mJIT, "Closure", rb_cObject);
|
1411
|
+
rb_define_method(rb_cClosure, "to_int", closure_to_int, 0);
|
1412
|
+
rb_define_method(rb_cClosure, "to_s", closure_to_s, 0);
|
1413
|
+
rb_define_method(rb_cClosure, "inspect", closure_inspect, 0);
|
1414
|
+
|
1415
|
+
rb_cFunction = rb_define_class_under(rb_mJIT, "Function", rb_cObject);
|
1416
|
+
rb_define_singleton_method(rb_cFunction, "new", function_s_new, -1);
|
1417
|
+
rb_define_method(rb_cFunction, "compile", function_compile, 0);
|
1418
|
+
rb_define_singleton_method(rb_cFunction, "compile", function_s_compile, -1);
|
1419
|
+
rb_define_method(rb_cFunction, "get_param", function_get_param, 1);
|
1420
|
+
init_insns();
|
1421
|
+
rb_define_method(rb_cFunction, "insn_call", function_insn_call, -1);
|
1422
|
+
rb_define_method(rb_cFunction, "insn_call_native", function_insn_call_native, -1);
|
1423
|
+
rb_define_method(rb_cFunction, "insn_return", function_insn_return, -1);
|
1424
|
+
rb_define_method(rb_cFunction, "apply", function_apply, -1);
|
1425
|
+
rb_define_alias(rb_cFunction, "call", "apply");
|
1426
|
+
rb_define_method(rb_cFunction, "value", function_value, -1);
|
1427
|
+
rb_define_method(rb_cFunction, "const", function_const, 2);
|
1428
|
+
rb_define_method(rb_cFunction, "optimization_level", function_optimization_level, 0);
|
1429
|
+
rb_define_method(rb_cFunction, "optimization_level=", function_set_optimization_level, 1);
|
1430
|
+
rb_define_singleton_method(rb_cFunction, "max_optimization_level", function_max_optimization_level, 0);
|
1431
|
+
rb_define_method(rb_cFunction, "dump", function_dump, 0);
|
1432
|
+
rb_define_method(rb_cFunction, "to_closure", function_to_closure, 0);
|
1433
|
+
rb_define_method(rb_cFunction, "context", function_get_context, 0);
|
1434
|
+
rb_define_method(rb_cFunction, "compiled?", function_is_compiled, 0);
|
1435
|
+
|
1436
|
+
rb_cType = rb_define_class_under(rb_mJIT, "Type", rb_cObject);
|
1437
|
+
rb_define_singleton_method(rb_cType, "create_signature", type_s_create_signature, 3);
|
1438
|
+
rb_define_singleton_method(rb_cType, "create_struct", type_s_create_struct, 1);
|
1439
|
+
rb_define_singleton_method(rb_cType, "create_pointer", type_s_create_pointer, 1);
|
1440
|
+
rb_define_method(rb_cType, "get_offset", type_get_offset, 1);
|
1441
|
+
rb_define_method(rb_cType, "set_offset", type_set_offset, 2);
|
1442
|
+
rb_define_method(rb_cType, "size", type_size, 0);
|
1443
|
+
rb_define_const(rb_cType, "VOID", wrap_type(jit_type_void));
|
1444
|
+
rb_define_const(rb_cType, "SBYTE", wrap_type(jit_type_sbyte));
|
1445
|
+
rb_define_const(rb_cType, "UBYTE", wrap_type(jit_type_ubyte));
|
1446
|
+
rb_define_const(rb_cType, "SHORT", wrap_type(jit_type_short));
|
1447
|
+
rb_define_const(rb_cType, "USHORT", wrap_type(jit_type_ushort));
|
1448
|
+
rb_define_const(rb_cType, "INT", wrap_type(jit_type_int));
|
1449
|
+
rb_define_const(rb_cType, "UINT", wrap_type(jit_type_uint));
|
1450
|
+
rb_define_const(rb_cType, "NINT", wrap_type(jit_type_nint));
|
1451
|
+
rb_define_const(rb_cType, "NUINT", wrap_type(jit_type_nuint));
|
1452
|
+
rb_define_const(rb_cType, "LONG", wrap_type(jit_type_long));
|
1453
|
+
rb_define_const(rb_cType, "ULONG", wrap_type(jit_type_ulong));
|
1454
|
+
rb_define_const(rb_cType, "FLOAT32", wrap_type(jit_type_float32));
|
1455
|
+
rb_define_const(rb_cType, "FLOAT64", wrap_type(jit_type_float64));
|
1456
|
+
rb_define_const(rb_cType, "NFLOAT", wrap_type(jit_type_nfloat));
|
1457
|
+
rb_define_const(rb_cType, "VOID_PTR", wrap_type(jit_type_void_ptr));
|
1458
|
+
|
1459
|
+
jit_type_VALUE = jit_type_create_tagged(jit_underlying_type_VALUE, RJT_OBJECT, 0, 0, 1);
|
1460
|
+
rb_define_const(rb_cType, "OBJECT", wrap_type(jit_type_VALUE));
|
1461
|
+
|
1462
|
+
jit_type_ID = jit_type_create_tagged(jit_underlying_type_ID, RJT_ID, 0, 0, 1);
|
1463
|
+
rb_define_const(rb_cType, "ID", wrap_type(jit_type_ID));
|
1464
|
+
|
1465
|
+
jit_type_Function_Ptr = jit_type_create_tagged(jit_underlying_type_ID, RJT_FUNCTION_PTR, 0, 0, 1);
|
1466
|
+
rb_define_const(rb_cType, "FUNCTION_PTR", wrap_type(jit_type_Function_Ptr));
|
1467
|
+
|
1468
|
+
{
|
1469
|
+
jit_type_t ruby_vararg_param_types[3];
|
1470
|
+
jit_type_t ruby_vararg_signature_untagged;
|
1471
|
+
ruby_vararg_param_types[0] = jit_type_int;
|
1472
|
+
ruby_vararg_param_types[1] = jit_type_void_ptr;
|
1473
|
+
ruby_vararg_param_types[2] = jit_type_VALUE;
|
1474
|
+
ruby_vararg_signature_untagged = jit_type_create_signature(
|
1475
|
+
jit_abi_cdecl,
|
1476
|
+
jit_type_VALUE,
|
1477
|
+
ruby_vararg_param_types,
|
1478
|
+
3,
|
1479
|
+
1);
|
1480
|
+
ruby_vararg_signature = jit_type_create_tagged(ruby_vararg_signature_untagged, RJT_RUBY_VARARG_SIGNATURE, 0, 0, 1);
|
1481
|
+
}
|
1482
|
+
rb_define_const(rb_cType, "RUBY_VARARG_SIGNATURE", wrap_type(ruby_vararg_signature));
|
1483
|
+
|
1484
|
+
rb_mABI = rb_define_module_under(rb_mJIT, "ABI");
|
1485
|
+
rb_define_const(rb_mABI, "CDECL", INT2NUM(jit_abi_cdecl));
|
1486
|
+
rb_define_const(rb_mABI, "VARARG", INT2NUM(jit_abi_vararg));
|
1487
|
+
rb_define_const(rb_mABI, "STDCALL", INT2NUM(jit_abi_stdcall));
|
1488
|
+
rb_define_const(rb_mABI, "FASTCALL", INT2NUM(jit_abi_fastcall));
|
1489
|
+
|
1490
|
+
rb_cValue = rb_define_class_under(rb_mJIT, "Value", rb_cObject);
|
1491
|
+
rb_define_singleton_method(rb_cValue, "new_value", value_s_new_value, 2);
|
1492
|
+
rb_define_method(rb_cValue, "to_s", value_to_s, 0);
|
1493
|
+
rb_define_method(rb_cValue, "inspect", value_inspect, 0);
|
1494
|
+
rb_define_method(rb_cValue, "valid?", value_is_valid, 0);
|
1495
|
+
rb_define_method(rb_cValue, "temporary?", value_is_temporary, 0);
|
1496
|
+
rb_define_method(rb_cValue, "local?", value_is_local, 0);
|
1497
|
+
rb_define_method(rb_cValue, "constant?", value_is_constant, 0);
|
1498
|
+
rb_define_method(rb_cValue, "volatile?", value_is_volatile, 0);
|
1499
|
+
rb_define_method(rb_cValue, "set_volatile", value_set_volatile, 0);
|
1500
|
+
rb_define_method(rb_cValue, "addressable?", value_is_addressable, 0);
|
1501
|
+
rb_define_method(rb_cValue, "addressable=", value_set_addressable, 0);
|
1502
|
+
rb_define_method(rb_cValue, "function", value_function, 0);
|
1503
|
+
rb_define_method(rb_cValue, "type", value_type, 0);
|
1504
|
+
rb_define_method(rb_cValue, "coerce", value_coerce, 1);
|
1505
|
+
|
1506
|
+
rb_cLabel = rb_define_class_under(rb_mJIT, "Label", rb_cObject);
|
1507
|
+
rb_define_singleton_method(rb_cLabel, "new", label_s_new, 0);
|
1508
|
+
|
1509
|
+
rb_mCall = rb_define_module_under(rb_mJIT, "Call");
|
1510
|
+
rb_define_const(rb_mCall, "NOTHROW", INT2NUM(JIT_CALL_NOTHROW));
|
1511
|
+
rb_define_const(rb_mCall, "NORETURN", INT2NUM(JIT_CALL_NORETURN));
|
1512
|
+
rb_define_const(rb_mCall, "TAIL", INT2NUM(JIT_CALL_TAIL));
|
1513
|
+
|
1514
|
+
/* VALUE rb_cModule = rb_define_module(); */
|
1515
|
+
rb_define_method(rb_cModule, "define_jit_method", module_define_jit_method, 2);
|
1516
|
+
|
1517
|
+
#ifdef NEED_MINIMAL_NODE
|
1518
|
+
Init_minimal_node();
|
1519
|
+
#endif
|
1520
|
+
}
|
1521
|
+
|