ruby-libjit 0.2.4 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/ext/extconf.rb +0 -9
- data/ext/jit_ext.c +19 -16
- metadata +24 -42
- data/ext/method_data.c +0 -385
- data/ext/method_data.c.rpp +0 -294
- data/ext/method_data.h +0 -11
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.5
|
data/ext/extconf.rb
CHANGED
@@ -30,15 +30,6 @@ have_func("rb_errinfo", "ruby.h")
|
|
30
30
|
have_func('fmemopen')
|
31
31
|
have_func("rb_ensure", "ruby.h")
|
32
32
|
|
33
|
-
if have_header('ruby/node.h') then
|
34
|
-
# ruby.h defines HAVE_RUBY_NODE_H, even though it is not there
|
35
|
-
$defs.push("-DREALLY_HAVE_RUBY_NODE_H")
|
36
|
-
elsif have_header('node.h') then
|
37
|
-
# okay
|
38
|
-
else
|
39
|
-
$defs.push("-DNEED_MINIMAL_NODE")
|
40
|
-
end
|
41
|
-
|
42
33
|
have_header('env.h')
|
43
34
|
|
44
35
|
checking_for("whether VALUE is a pointer") do
|
data/ext/jit_ext.c
CHANGED
@@ -14,11 +14,6 @@
|
|
14
14
|
#include <jit/jit-dump.h>
|
15
15
|
|
16
16
|
#include "rubyjit.h"
|
17
|
-
#include "method_data.h"
|
18
|
-
|
19
|
-
#ifdef NEED_MINIMAL_NODE
|
20
|
-
#include "minimal_node.h"
|
21
|
-
#endif
|
22
17
|
|
23
18
|
#ifndef RARRAY_LEN
|
24
19
|
#define RARRAY_LEN(a) RARRAY(a)->len
|
@@ -38,6 +33,8 @@ static VALUE rb_cLabel;
|
|
38
33
|
static VALUE rb_mCall;
|
39
34
|
static VALUE rb_cClosure;
|
40
35
|
|
36
|
+
static VALUE closures;
|
37
|
+
|
41
38
|
jit_type_t jit_type_VALUE;
|
42
39
|
jit_type_t jit_type_ID;
|
43
40
|
jit_type_t jit_type_Function_Ptr;
|
@@ -223,8 +220,9 @@ static void mark_closure(struct Closure * closure)
|
|
223
220
|
VALUE closure_to_int(VALUE self)
|
224
221
|
{
|
225
222
|
struct Closure * closure;
|
223
|
+
VALUE v;
|
226
224
|
Data_Get_Struct(self, struct Closure, closure);
|
227
|
-
|
225
|
+
v = ULONG2NUM((unsigned long)closure->function_ptr);
|
228
226
|
return v;
|
229
227
|
}
|
230
228
|
|
@@ -646,7 +644,7 @@ static VALUE function_insn_call(int argc, VALUE * argv, VALUE self)
|
|
646
644
|
|
647
645
|
Data_Get_Struct(self, struct _jit_function, function);
|
648
646
|
|
649
|
-
name =
|
647
|
+
name = StringValuePtr(name_v);
|
650
648
|
|
651
649
|
check_type("called function", rb_cFunction, called_function_v);
|
652
650
|
Data_Get_Struct(called_function_v, struct _jit_function, called_function);
|
@@ -712,7 +710,7 @@ static VALUE function_insn_call_native(int argc, VALUE * argv, VALUE self)
|
|
712
710
|
{
|
713
711
|
rb_raise(
|
714
712
|
rb_eArgError,
|
715
|
-
"Wrong number of arguments passed for %s (expecting %d but got %
|
713
|
+
"Wrong number of arguments passed for %s (expecting %d but got %zd)",
|
716
714
|
name,
|
717
715
|
jit_type_num_params(signature),
|
718
716
|
num_args);
|
@@ -1426,7 +1424,7 @@ static VALUE module_define_jit_method(VALUE klass, VALUE name_v, VALUE function_
|
|
1426
1424
|
}
|
1427
1425
|
else
|
1428
1426
|
{
|
1429
|
-
name =
|
1427
|
+
name = StringValuePtr(name_v);
|
1430
1428
|
}
|
1431
1429
|
|
1432
1430
|
Data_Get_Struct(function_v, struct _jit_function, function);
|
@@ -1445,9 +1443,15 @@ static VALUE module_define_jit_method(VALUE klass, VALUE name_v, VALUE function_
|
|
1445
1443
|
|
1446
1444
|
closure_v = function_to_closure(function_v);
|
1447
1445
|
Data_Get_Struct(closure_v, struct Closure, closure);
|
1448
|
-
|
1449
|
-
|
1450
|
-
|
1446
|
+
|
1447
|
+
/* TODO: This will leak the closure if the method is ever redefined.
|
1448
|
+
* I had a solution to this problem, but it became too convoluted to
|
1449
|
+
* maintain.
|
1450
|
+
*/
|
1451
|
+
rb_ary_push(closures, closure_v);
|
1452
|
+
rb_define_method(
|
1453
|
+
klass, name, RUBY_METHOD_FUNC(closure->function_ptr), arity);
|
1454
|
+
|
1451
1455
|
return Qnil;
|
1452
1456
|
}
|
1453
1457
|
|
@@ -1460,6 +1464,9 @@ void Init_jit_ext()
|
|
1460
1464
|
{
|
1461
1465
|
jit_init();
|
1462
1466
|
|
1467
|
+
closures = rb_ary_new();
|
1468
|
+
rb_gc_register_address(&closures);
|
1469
|
+
|
1463
1470
|
rb_mJIT = rb_define_module("JIT");
|
1464
1471
|
|
1465
1472
|
rb_cContext = rb_define_class_under(rb_mJIT, "Context", rb_cObject);
|
@@ -1575,9 +1582,5 @@ void Init_jit_ext()
|
|
1575
1582
|
|
1576
1583
|
/* VALUE rb_cModule = rb_define_module(); */
|
1577
1584
|
rb_define_method(rb_cModule, "define_jit_method", module_define_jit_method, 2);
|
1578
|
-
|
1579
|
-
#ifdef NEED_MINIMAL_NODE
|
1580
|
-
Init_minimal_node();
|
1581
|
-
#endif
|
1582
1585
|
}
|
1583
1586
|
|
metadata
CHANGED
@@ -1,37 +1,31 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-libjit
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.5
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 2
|
9
|
-
- 4
|
10
|
-
version: 0.2.4
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Paul Brannan
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
date: 2012-05-03 00:00:00 Z
|
12
|
+
date: 2012-05-09 00:00:00.000000000 Z
|
19
13
|
dependencies: []
|
14
|
+
description: ! 'Ruby-libjit is a wrapper for the libjit library. Libjit is a
|
20
15
|
|
21
|
-
description: |
|
22
|
-
Ruby-libjit is a wrapper for the libjit library. Libjit is a
|
23
16
|
lightweight library for building just-in-time compilers. Ruby-libjit
|
17
|
+
|
24
18
|
includes both a wrapper for libjit and a minimal DSL for building loops
|
19
|
+
|
25
20
|
and control structures.
|
26
21
|
|
22
|
+
'
|
27
23
|
email: curlypaul924@gmail.com
|
28
24
|
executables: []
|
29
|
-
|
30
|
-
extensions:
|
25
|
+
extensions:
|
31
26
|
- ext/extconf.rb
|
32
27
|
extra_rdoc_files: []
|
33
|
-
|
34
|
-
files:
|
28
|
+
files:
|
35
29
|
- VERSION
|
36
30
|
- COPYING
|
37
31
|
- LGPL
|
@@ -46,14 +40,11 @@ files:
|
|
46
40
|
- lib/jit/pointer.rb
|
47
41
|
- ext/extconf.rb
|
48
42
|
- ext/rubypp.rb
|
49
|
-
- ext/method_data.c
|
50
43
|
- ext/jit_ext.c
|
51
44
|
- ext/minimal_node.c
|
52
45
|
- ext/rubyjit.h
|
53
46
|
- ext/minimal_node.h
|
54
|
-
- ext/method_data.h
|
55
47
|
- ext/insns.inc.rpp
|
56
|
-
- ext/method_data.c.rpp
|
57
48
|
- sample/simple.rb
|
58
49
|
- sample/fib.rb
|
59
50
|
- sample/gcd_benchmark.rb
|
@@ -64,38 +55,29 @@ files:
|
|
64
55
|
- test/test_jit_value.rb
|
65
56
|
homepage: http://ruby-libjit.rubyforge.org
|
66
57
|
licenses: []
|
67
|
-
|
68
58
|
post_install_message:
|
69
59
|
rdoc_options: []
|
70
|
-
|
71
|
-
require_paths:
|
60
|
+
require_paths:
|
72
61
|
- lib
|
73
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
63
|
none: false
|
75
|
-
requirements:
|
76
|
-
- -
|
77
|
-
- !ruby/object:Gem::Version
|
78
|
-
|
79
|
-
|
80
|
-
- 0
|
81
|
-
version: "0"
|
82
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ! '>='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
69
|
none: false
|
84
|
-
requirements:
|
85
|
-
- -
|
86
|
-
- !ruby/object:Gem::Version
|
87
|
-
|
88
|
-
segments:
|
89
|
-
- 0
|
90
|
-
version: "0"
|
70
|
+
requirements:
|
71
|
+
- - ! '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
91
74
|
requirements: []
|
92
|
-
|
93
75
|
rubyforge_project: ruby-libjit
|
94
|
-
rubygems_version: 1.
|
76
|
+
rubygems_version: 1.8.24
|
95
77
|
signing_key:
|
96
78
|
specification_version: 3
|
97
79
|
summary: A wrapper for the libjit library
|
98
|
-
test_files:
|
80
|
+
test_files:
|
99
81
|
- test/test_jit_array.rb
|
100
82
|
- test/test_jit_pointer.rb
|
101
83
|
- test/test_jit_function.rb
|
data/ext/method_data.c
DELETED
@@ -1,385 +0,0 @@
|
|
1
|
-
#include "method_data.h"
|
2
|
-
|
3
|
-
#include <ruby.h>
|
4
|
-
|
5
|
-
#ifndef HAVE_RUBINIUS
|
6
|
-
|
7
|
-
|
8
|
-
#if defined(HAVE_NODE_H)
|
9
|
-
/* pre-YARV */
|
10
|
-
#include <node.h>
|
11
|
-
#elif defined(REALLY_HAVE_RUBY_NODE_H)
|
12
|
-
/* YARV */
|
13
|
-
#include <ruby/node.h>
|
14
|
-
#elif defined(RUBY_VM)
|
15
|
-
/* YARV without node.h */
|
16
|
-
#include "minimal_node.h"
|
17
|
-
#else
|
18
|
-
/* something else */
|
19
|
-
#error "Need node.h"
|
20
|
-
#endif
|
21
|
-
|
22
|
-
#ifdef HAVE_ENV_H
|
23
|
-
/* pre-YARV */
|
24
|
-
#include <env.h>
|
25
|
-
#endif
|
26
|
-
|
27
|
-
#ifdef RUBY_VM
|
28
|
-
|
29
|
-
/* YARV */
|
30
|
-
|
31
|
-
struct rb_thread_struct
|
32
|
-
{
|
33
|
-
VALUE self;
|
34
|
-
void *vm;
|
35
|
-
VALUE *stack;
|
36
|
-
unsigned long stack_size;
|
37
|
-
VALUE *cfp;
|
38
|
-
/* ... */
|
39
|
-
};
|
40
|
-
|
41
|
-
typedef struct rb_thread_struct rb_thread_t;
|
42
|
-
|
43
|
-
#define CFP_DATA_MEMO_NODE_AND_PC cfp[0]
|
44
|
-
#define CFP_METHOD_CLASS cfp[11]
|
45
|
-
|
46
|
-
/* On YARV, we store the method data on the stack. We don't have to pop
|
47
|
-
* it off the stack, because the stack pointer will be reset to the
|
48
|
-
* previous frame's stack pointer when the function returns.
|
49
|
-
*/
|
50
|
-
static void fix_frame()
|
51
|
-
{
|
52
|
-
do {
|
53
|
-
extern rb_thread_t * ruby_current_thread;
|
54
|
-
VALUE * cfp = ruby_current_thread->cfp;
|
55
|
-
CFP_DATA_MEMO_NODE_AND_PC = RBASIC(CFP_METHOD_CLASS)->klass;
|
56
|
-
|
57
|
-
if(rb_type(CFP_DATA_MEMO_NODE_AND_PC) != T_NODE)
|
58
|
-
{
|
59
|
-
/* This can happen for module functions that are created after
|
60
|
-
* the stub function */
|
61
|
-
rb_raise(
|
62
|
-
rb_eRuntimeError,
|
63
|
-
"Cannot find method data for module function");
|
64
|
-
}
|
65
|
-
else
|
66
|
-
{
|
67
|
-
CFP_METHOD_CLASS = RCLASS_SUPER(CFP_METHOD_CLASS);
|
68
|
-
}
|
69
|
-
} while(0);
|
70
|
-
}
|
71
|
-
|
72
|
-
#define FIX_FRAME() \
|
73
|
-
fix_frame()
|
74
|
-
|
75
|
-
static NODE * data_memo_node()
|
76
|
-
{
|
77
|
-
extern rb_thread_t * ruby_current_thread;
|
78
|
-
VALUE * cfp = ruby_current_thread->cfp;
|
79
|
-
return (NODE *)CFP_DATA_MEMO_NODE_AND_PC;
|
80
|
-
}
|
81
|
-
|
82
|
-
#else
|
83
|
-
|
84
|
-
/* pre-YARV */
|
85
|
-
|
86
|
-
/* Okay to not pop this temporary frame, since it will be popped by the
|
87
|
-
* caller
|
88
|
-
*/
|
89
|
-
#define FIX_FRAME() \
|
90
|
-
struct FRAME _frame = *ruby_frame; \
|
91
|
-
_frame.last_class = RCLASS(ruby_frame->last_class)->super; \
|
92
|
-
_frame.prev = ruby_frame; \
|
93
|
-
ruby_frame = &_frame; \
|
94
|
-
|
95
|
-
static NODE * data_memo_node()
|
96
|
-
{
|
97
|
-
return (NODE *)(RBASIC(ruby_frame->prev->last_class)->klass);
|
98
|
-
}
|
99
|
-
|
100
|
-
#endif
|
101
|
-
|
102
|
-
typedef VALUE (*Method_Func)(ANYARGS);
|
103
|
-
|
104
|
-
static Method_Func actual_cfunc()
|
105
|
-
{
|
106
|
-
return data_memo_node()->nd_cfnc;
|
107
|
-
}
|
108
|
-
|
109
|
-
static VALUE data_wrapper_m1(int argc, VALUE * argv, VALUE self)
|
110
|
-
{
|
111
|
-
VALUE result;
|
112
|
-
FIX_FRAME();
|
113
|
-
result = (*actual_cfunc())(argc, argv, self);
|
114
|
-
return result;
|
115
|
-
}
|
116
|
-
|
117
|
-
static VALUE data_wrapper_0(VALUE self)
|
118
|
-
{
|
119
|
-
VALUE result;
|
120
|
-
FIX_FRAME();
|
121
|
-
result = (*actual_cfunc())(self);
|
122
|
-
return result;
|
123
|
-
}
|
124
|
-
|
125
|
-
static VALUE data_wrapper_1(VALUE self, VALUE arg1)
|
126
|
-
{
|
127
|
-
VALUE result;
|
128
|
-
FIX_FRAME();
|
129
|
-
result = (*actual_cfunc())(self, arg1);
|
130
|
-
return result;
|
131
|
-
}
|
132
|
-
static VALUE data_wrapper_2(VALUE self, VALUE arg1, VALUE arg2)
|
133
|
-
{
|
134
|
-
VALUE result;
|
135
|
-
FIX_FRAME();
|
136
|
-
result = (*actual_cfunc())(self, arg1, arg2);
|
137
|
-
return result;
|
138
|
-
}
|
139
|
-
static VALUE data_wrapper_3(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3)
|
140
|
-
{
|
141
|
-
VALUE result;
|
142
|
-
FIX_FRAME();
|
143
|
-
result = (*actual_cfunc())(self, arg1, arg2, arg3);
|
144
|
-
return result;
|
145
|
-
}
|
146
|
-
static VALUE data_wrapper_4(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4)
|
147
|
-
{
|
148
|
-
VALUE result;
|
149
|
-
FIX_FRAME();
|
150
|
-
result = (*actual_cfunc())(self, arg1, arg2, arg3, arg4);
|
151
|
-
return result;
|
152
|
-
}
|
153
|
-
static VALUE data_wrapper_5(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4, VALUE arg5)
|
154
|
-
{
|
155
|
-
VALUE result;
|
156
|
-
FIX_FRAME();
|
157
|
-
result = (*actual_cfunc())(self, arg1, arg2, arg3, arg4, arg5);
|
158
|
-
return result;
|
159
|
-
}
|
160
|
-
static VALUE data_wrapper_6(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4, VALUE arg5, VALUE arg6)
|
161
|
-
{
|
162
|
-
VALUE result;
|
163
|
-
FIX_FRAME();
|
164
|
-
result = (*actual_cfunc())(self, arg1, arg2, arg3, arg4, arg5, arg6);
|
165
|
-
return result;
|
166
|
-
}
|
167
|
-
static VALUE data_wrapper_7(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4, VALUE arg5, VALUE arg6, VALUE arg7)
|
168
|
-
{
|
169
|
-
VALUE result;
|
170
|
-
FIX_FRAME();
|
171
|
-
result = (*actual_cfunc())(self, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
|
172
|
-
return result;
|
173
|
-
}
|
174
|
-
static VALUE data_wrapper_8(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4, VALUE arg5, VALUE arg6, VALUE arg7, VALUE arg8)
|
175
|
-
{
|
176
|
-
VALUE result;
|
177
|
-
FIX_FRAME();
|
178
|
-
result = (*actual_cfunc())(self, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
|
179
|
-
return result;
|
180
|
-
}
|
181
|
-
static VALUE data_wrapper_9(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4, VALUE arg5, VALUE arg6, VALUE arg7, VALUE arg8, VALUE arg9)
|
182
|
-
{
|
183
|
-
VALUE result;
|
184
|
-
FIX_FRAME();
|
185
|
-
result = (*actual_cfunc())(self, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
|
186
|
-
return result;
|
187
|
-
}
|
188
|
-
static VALUE data_wrapper_10(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4, VALUE arg5, VALUE arg6, VALUE arg7, VALUE arg8, VALUE arg9, VALUE arg10)
|
189
|
-
{
|
190
|
-
VALUE result;
|
191
|
-
FIX_FRAME();
|
192
|
-
result = (*actual_cfunc())(self, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
|
193
|
-
return result;
|
194
|
-
}
|
195
|
-
static VALUE data_wrapper_11(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4, VALUE arg5, VALUE arg6, VALUE arg7, VALUE arg8, VALUE arg9, VALUE arg10, VALUE arg11)
|
196
|
-
{
|
197
|
-
VALUE result;
|
198
|
-
FIX_FRAME();
|
199
|
-
result = (*actual_cfunc())(self, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11);
|
200
|
-
return result;
|
201
|
-
}
|
202
|
-
static VALUE data_wrapper_12(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4, VALUE arg5, VALUE arg6, VALUE arg7, VALUE arg8, VALUE arg9, VALUE arg10, VALUE arg11, VALUE arg12)
|
203
|
-
{
|
204
|
-
VALUE result;
|
205
|
-
FIX_FRAME();
|
206
|
-
result = (*actual_cfunc())(self, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12);
|
207
|
-
return result;
|
208
|
-
}
|
209
|
-
static VALUE data_wrapper_13(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4, VALUE arg5, VALUE arg6, VALUE arg7, VALUE arg8, VALUE arg9, VALUE arg10, VALUE arg11, VALUE arg12, VALUE arg13)
|
210
|
-
{
|
211
|
-
VALUE result;
|
212
|
-
FIX_FRAME();
|
213
|
-
result = (*actual_cfunc())(self, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13);
|
214
|
-
return result;
|
215
|
-
}
|
216
|
-
static VALUE data_wrapper_14(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4, VALUE arg5, VALUE arg6, VALUE arg7, VALUE arg8, VALUE arg9, VALUE arg10, VALUE arg11, VALUE arg12, VALUE arg13, VALUE arg14)
|
217
|
-
{
|
218
|
-
VALUE result;
|
219
|
-
FIX_FRAME();
|
220
|
-
result = (*actual_cfunc())(self, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14);
|
221
|
-
return result;
|
222
|
-
}
|
223
|
-
static VALUE data_wrapper_15(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4, VALUE arg5, VALUE arg6, VALUE arg7, VALUE arg8, VALUE arg9, VALUE arg10, VALUE arg11, VALUE arg12, VALUE arg13, VALUE arg14, VALUE arg15)
|
224
|
-
{
|
225
|
-
VALUE result;
|
226
|
-
FIX_FRAME();
|
227
|
-
result = (*actual_cfunc())(self, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15);
|
228
|
-
return result;
|
229
|
-
}
|
230
|
-
|
231
|
-
/* Define a method and attach data to it.
|
232
|
-
*
|
233
|
-
* The method looks to ruby like a normal aliased CFUNC, with a modified
|
234
|
-
* origin class:
|
235
|
-
*
|
236
|
-
* NODE_FBODY
|
237
|
-
* |- (u1) orig - origin class
|
238
|
-
* | |- basic
|
239
|
-
* | | |- flags - origin class flags + FL_SINGLETON
|
240
|
-
* | | +- klass - NODE_MEMO
|
241
|
-
* | | |- (u1) cfnc - actual C function to call
|
242
|
-
* | | |- (u2) rval - stored data
|
243
|
-
* | | +- (u3) 0
|
244
|
-
* | |- iv_tbl - 0
|
245
|
-
* | |- m_tbl - 0
|
246
|
-
* | +- super - actual origin class
|
247
|
-
* |- (u2) mid - name of the method
|
248
|
-
* +- (u3) head - NODE_CFUNC
|
249
|
-
* |- (u1) cfnc - wrapper function to call
|
250
|
-
* +- (u2) argc - function arity
|
251
|
-
*
|
252
|
-
* Or, on YARV:
|
253
|
-
*
|
254
|
-
* NODE_FBODY
|
255
|
-
* |- (u1) oid - name of the method
|
256
|
-
* +- (u2) body - NODE_METHOD
|
257
|
-
* |- (u1) clss - origin class
|
258
|
-
* | |- basic
|
259
|
-
* | | |- flags - origin class flags + FL_SINGLETON
|
260
|
-
* | | +- klass - NODE_MEMO
|
261
|
-
* | | |- (u1) cfnc - actual C function to call
|
262
|
-
* | | |- (u2) rval - stored data
|
263
|
-
* | | +- (u3) 0
|
264
|
-
* | |- ptr - rb_classext_t
|
265
|
-
* | | |- super - actual origin class
|
266
|
-
* | | +- iv_tbl - 0
|
267
|
-
* | |- m_tbl - 0
|
268
|
-
* | +- iv_index_tbl - 0?
|
269
|
-
* |- (u2) body - NODE_CFUNC
|
270
|
-
* | |- (u1) cfnc - wrapper function to call
|
271
|
-
* | |- (u2) argc - function arity
|
272
|
-
* +- (u3) noex - NOEX_PUBLIC
|
273
|
-
*
|
274
|
-
* When the wrapper function is called, last_class is set to the origin
|
275
|
-
* class found in the FBODY node. So that the method data will be
|
276
|
-
* accessible, and so last_class will point to klass and not to our MEMO
|
277
|
-
* node, it is necessary to "fix" the current frame.
|
278
|
-
*
|
279
|
-
* Pre-YARV, this means we duplicate the current frame and set last_class:
|
280
|
-
*
|
281
|
-
* ruby_frame
|
282
|
-
* |- last_class - klass
|
283
|
-
* |- prev
|
284
|
-
* | |- last_class - NODE_MEMO
|
285
|
-
* | | |- (u1) cfnc - actual C function to call
|
286
|
-
* | | |- (u2) rval - stored data
|
287
|
-
* | | +- (u3) 0
|
288
|
-
* | |- prev - the real previous frame
|
289
|
-
* | +- ...
|
290
|
-
* +- ...
|
291
|
-
*
|
292
|
-
* The method data is then accessible via
|
293
|
-
* ruby_frame->prev->last_class->rval.
|
294
|
-
*
|
295
|
-
* On YARV, the current frame is not duplicated; rather, the method data
|
296
|
-
* is placed on the stack and is referenced by one of the unused members
|
297
|
-
* of the control frame (the program counter):
|
298
|
-
*
|
299
|
-
* ruby_current_thread->cfp
|
300
|
-
* |- pc - NODE_MEMO
|
301
|
-
* | |- (u1) cfnc - actual C function to call
|
302
|
-
* | |- (u2) rval - stored data
|
303
|
-
* | +- (u3) 0
|
304
|
-
* |- method_class - klass
|
305
|
-
* +- ...
|
306
|
-
*
|
307
|
-
*/
|
308
|
-
void define_method_with_data(
|
309
|
-
VALUE klass, ID id, VALUE (*cfunc)(ANYARGS), int arity, VALUE data)
|
310
|
-
{
|
311
|
-
/* TODO: origin should have #to_s and #inspect methods defined */
|
312
|
-
#ifdef HAVE_RB_CLASS_BOOT
|
313
|
-
VALUE origin = rb_class_boot(klass);
|
314
|
-
#else
|
315
|
-
VALUE origin = rb_class_new(klass);
|
316
|
-
#endif
|
317
|
-
NODE * node;
|
318
|
-
|
319
|
-
VALUE (*data_wrapper)(ANYARGS);
|
320
|
-
switch(arity)
|
321
|
-
{
|
322
|
-
case 0: data_wrapper = RUBY_METHOD_FUNC(data_wrapper_0); break;
|
323
|
-
case 1: data_wrapper = RUBY_METHOD_FUNC(data_wrapper_1); break;
|
324
|
-
case 2: data_wrapper = RUBY_METHOD_FUNC(data_wrapper_2); break;
|
325
|
-
case 3: data_wrapper = RUBY_METHOD_FUNC(data_wrapper_3); break;
|
326
|
-
case 4: data_wrapper = RUBY_METHOD_FUNC(data_wrapper_4); break;
|
327
|
-
case 5: data_wrapper = RUBY_METHOD_FUNC(data_wrapper_5); break;
|
328
|
-
case 6: data_wrapper = RUBY_METHOD_FUNC(data_wrapper_6); break;
|
329
|
-
case 7: data_wrapper = RUBY_METHOD_FUNC(data_wrapper_7); break;
|
330
|
-
case 8: data_wrapper = RUBY_METHOD_FUNC(data_wrapper_8); break;
|
331
|
-
case 9: data_wrapper = RUBY_METHOD_FUNC(data_wrapper_9); break;
|
332
|
-
case 10: data_wrapper = RUBY_METHOD_FUNC(data_wrapper_10); break;
|
333
|
-
case 11: data_wrapper = RUBY_METHOD_FUNC(data_wrapper_11); break;
|
334
|
-
case 12: data_wrapper = RUBY_METHOD_FUNC(data_wrapper_12); break;
|
335
|
-
case 13: data_wrapper = RUBY_METHOD_FUNC(data_wrapper_13); break;
|
336
|
-
case 14: data_wrapper = RUBY_METHOD_FUNC(data_wrapper_14); break;
|
337
|
-
case 15: data_wrapper = RUBY_METHOD_FUNC(data_wrapper_15); break;
|
338
|
-
case -1: data_wrapper = RUBY_METHOD_FUNC(data_wrapper_m1); break;
|
339
|
-
default: rb_raise(rb_eArgError, "unsupported arity %d", arity);
|
340
|
-
}
|
341
|
-
|
342
|
-
FL_SET(origin, FL_SINGLETON);
|
343
|
-
rb_singleton_class_attached(origin, klass);
|
344
|
-
rb_name_class(origin, SYM2ID(rb_class_name(klass)));
|
345
|
-
|
346
|
-
RBASIC(origin)->klass = (VALUE)NEW_NODE(NODE_MEMO, cfunc, data, 0);
|
347
|
-
|
348
|
-
#ifdef RUBY_VM
|
349
|
-
/* YARV */
|
350
|
-
node = NEW_FBODY(
|
351
|
-
NEW_METHOD(
|
352
|
-
NEW_CFUNC(data_wrapper, arity),
|
353
|
-
origin,
|
354
|
-
NOEX_PUBLIC),
|
355
|
-
id);
|
356
|
-
st_insert(RCLASS_M_TBL(klass), id, (st_data_t)node);
|
357
|
-
#else
|
358
|
-
/* pre-YARV */
|
359
|
-
node = NEW_FBODY(
|
360
|
-
NEW_CFUNC(data_wrapper, arity),
|
361
|
-
id,
|
362
|
-
origin);
|
363
|
-
rb_add_method(klass, id, node, NOEX_PUBLIC);
|
364
|
-
#endif
|
365
|
-
}
|
366
|
-
|
367
|
-
VALUE get_method_data()
|
368
|
-
{
|
369
|
-
return data_memo_node()->nd_rval;
|
370
|
-
}
|
371
|
-
|
372
|
-
#else /* HAVE_RUBINIUS */
|
373
|
-
|
374
|
-
void define_method_with_data(
|
375
|
-
VALUE klass, ID id, VALUE (*cfunc)(ANYARGS), int arity, VALUE data)
|
376
|
-
{
|
377
|
-
rb_raise(rb_eNotImpError, "Not implemented: define_method_with_data");
|
378
|
-
}
|
379
|
-
|
380
|
-
VALUE get_method_data()
|
381
|
-
{
|
382
|
-
rb_raise(rb_eNotImpError, "Not implemented: get_method_data");
|
383
|
-
}
|
384
|
-
|
385
|
-
#endif
|
data/ext/method_data.c.rpp
DELETED
@@ -1,294 +0,0 @@
|
|
1
|
-
#include "method_data.h"
|
2
|
-
|
3
|
-
#include <ruby.h>
|
4
|
-
|
5
|
-
#ifndef HAVE_RUBINIUS
|
6
|
-
|
7
|
-
#ruby <<END
|
8
|
-
MAX_ARGS = 15
|
9
|
-
nil
|
10
|
-
END
|
11
|
-
|
12
|
-
#if defined(HAVE_NODE_H)
|
13
|
-
/* pre-YARV */
|
14
|
-
#include <node.h>
|
15
|
-
#elif defined(REALLY_HAVE_RUBY_NODE_H)
|
16
|
-
/* YARV */
|
17
|
-
#include <ruby/node.h>
|
18
|
-
#elif defined(RUBY_VM)
|
19
|
-
/* YARV without node.h */
|
20
|
-
#include "minimal_node.h"
|
21
|
-
#else
|
22
|
-
/* something else */
|
23
|
-
#error "Need node.h"
|
24
|
-
#endif
|
25
|
-
|
26
|
-
#ifdef HAVE_ENV_H
|
27
|
-
/* pre-YARV */
|
28
|
-
#include <env.h>
|
29
|
-
#endif
|
30
|
-
|
31
|
-
#ifdef RUBY_VM
|
32
|
-
|
33
|
-
/* YARV */
|
34
|
-
|
35
|
-
struct rb_thread_struct
|
36
|
-
{
|
37
|
-
VALUE self;
|
38
|
-
void *vm;
|
39
|
-
VALUE *stack;
|
40
|
-
unsigned long stack_size;
|
41
|
-
VALUE *cfp;
|
42
|
-
/* ... */
|
43
|
-
};
|
44
|
-
|
45
|
-
typedef struct rb_thread_struct rb_thread_t;
|
46
|
-
|
47
|
-
#define CFP_DATA_MEMO_NODE_AND_PC cfp[0]
|
48
|
-
#define CFP_METHOD_CLASS cfp[11]
|
49
|
-
|
50
|
-
/* On YARV, we store the method data on the stack. We don't have to pop
|
51
|
-
* it off the stack, because the stack pointer will be reset to the
|
52
|
-
* previous frame's stack pointer when the function returns.
|
53
|
-
*/
|
54
|
-
static void fix_frame()
|
55
|
-
{
|
56
|
-
do {
|
57
|
-
extern rb_thread_t * ruby_current_thread;
|
58
|
-
VALUE * cfp = ruby_current_thread->cfp;
|
59
|
-
CFP_DATA_MEMO_NODE_AND_PC = RBASIC(CFP_METHOD_CLASS)->klass;
|
60
|
-
|
61
|
-
if(rb_type(CFP_DATA_MEMO_NODE_AND_PC) != T_NODE)
|
62
|
-
{
|
63
|
-
/* This can happen for module functions that are created after
|
64
|
-
* the stub function */
|
65
|
-
rb_raise(
|
66
|
-
rb_eRuntimeError,
|
67
|
-
"Cannot find method data for module function");
|
68
|
-
}
|
69
|
-
else
|
70
|
-
{
|
71
|
-
CFP_METHOD_CLASS = RCLASS_SUPER(CFP_METHOD_CLASS);
|
72
|
-
}
|
73
|
-
} while(0);
|
74
|
-
}
|
75
|
-
|
76
|
-
#define FIX_FRAME() \
|
77
|
-
fix_frame()
|
78
|
-
|
79
|
-
static NODE * data_memo_node()
|
80
|
-
{
|
81
|
-
extern rb_thread_t * ruby_current_thread;
|
82
|
-
VALUE * cfp = ruby_current_thread->cfp;
|
83
|
-
return (NODE *)CFP_DATA_MEMO_NODE_AND_PC;
|
84
|
-
}
|
85
|
-
|
86
|
-
#else
|
87
|
-
|
88
|
-
/* pre-YARV */
|
89
|
-
|
90
|
-
/* Okay to not pop this temporary frame, since it will be popped by the
|
91
|
-
* caller
|
92
|
-
*/
|
93
|
-
#define FIX_FRAME() \
|
94
|
-
struct FRAME _frame = *ruby_frame; \
|
95
|
-
_frame.last_class = RCLASS(ruby_frame->last_class)->super; \
|
96
|
-
_frame.prev = ruby_frame; \
|
97
|
-
ruby_frame = &_frame; \
|
98
|
-
|
99
|
-
static NODE * data_memo_node()
|
100
|
-
{
|
101
|
-
return (NODE *)(RBASIC(ruby_frame->prev->last_class)->klass);
|
102
|
-
}
|
103
|
-
|
104
|
-
#endif
|
105
|
-
|
106
|
-
typedef VALUE (*Method_Func)(ANYARGS);
|
107
|
-
|
108
|
-
static Method_Func actual_cfunc()
|
109
|
-
{
|
110
|
-
return data_memo_node()->nd_cfnc;
|
111
|
-
}
|
112
|
-
|
113
|
-
static VALUE data_wrapper_m1(int argc, VALUE * argv, VALUE self)
|
114
|
-
{
|
115
|
-
VALUE result;
|
116
|
-
FIX_FRAME();
|
117
|
-
result = (*actual_cfunc())(argc, argv, self);
|
118
|
-
return result;
|
119
|
-
}
|
120
|
-
|
121
|
-
static VALUE data_wrapper_0(VALUE self)
|
122
|
-
{
|
123
|
-
VALUE result;
|
124
|
-
FIX_FRAME();
|
125
|
-
result = (*actual_cfunc())(self);
|
126
|
-
return result;
|
127
|
-
}
|
128
|
-
|
129
|
-
#ruby <<END
|
130
|
-
(1..MAX_ARGS).each do |i|
|
131
|
-
params = (1..i).map { |j| "VALUE arg#{j}" }.join(', ')
|
132
|
-
args = (1..i).map { |j| "arg#{j}" }.join(', ')
|
133
|
-
|
134
|
-
puts <<-END
|
135
|
-
static VALUE data_wrapper_#{i}(VALUE self, #{params})
|
136
|
-
{
|
137
|
-
VALUE result;
|
138
|
-
FIX_FRAME();
|
139
|
-
result = (*actual_cfunc())(self, #{args});
|
140
|
-
return result;
|
141
|
-
}
|
142
|
-
END
|
143
|
-
end
|
144
|
-
|
145
|
-
nil
|
146
|
-
END
|
147
|
-
|
148
|
-
/* Define a method and attach data to it.
|
149
|
-
*
|
150
|
-
* The method looks to ruby like a normal aliased CFUNC, with a modified
|
151
|
-
* origin class:
|
152
|
-
*
|
153
|
-
* NODE_FBODY
|
154
|
-
* |- (u1) orig - origin class
|
155
|
-
* | |- basic
|
156
|
-
* | | |- flags - origin class flags + FL_SINGLETON
|
157
|
-
* | | +- klass - NODE_MEMO
|
158
|
-
* | | |- (u1) cfnc - actual C function to call
|
159
|
-
* | | |- (u2) rval - stored data
|
160
|
-
* | | +- (u3) 0
|
161
|
-
* | |- iv_tbl - 0
|
162
|
-
* | |- m_tbl - 0
|
163
|
-
* | +- super - actual origin class
|
164
|
-
* |- (u2) mid - name of the method
|
165
|
-
* +- (u3) head - NODE_CFUNC
|
166
|
-
* |- (u1) cfnc - wrapper function to call
|
167
|
-
* +- (u2) argc - function arity
|
168
|
-
*
|
169
|
-
* Or, on YARV:
|
170
|
-
*
|
171
|
-
* NODE_FBODY
|
172
|
-
* |- (u1) oid - name of the method
|
173
|
-
* +- (u2) body - NODE_METHOD
|
174
|
-
* |- (u1) clss - origin class
|
175
|
-
* | |- basic
|
176
|
-
* | | |- flags - origin class flags + FL_SINGLETON
|
177
|
-
* | | +- klass - NODE_MEMO
|
178
|
-
* | | |- (u1) cfnc - actual C function to call
|
179
|
-
* | | |- (u2) rval - stored data
|
180
|
-
* | | +- (u3) 0
|
181
|
-
* | |- ptr - rb_classext_t
|
182
|
-
* | | |- super - actual origin class
|
183
|
-
* | | +- iv_tbl - 0
|
184
|
-
* | |- m_tbl - 0
|
185
|
-
* | +- iv_index_tbl - 0?
|
186
|
-
* |- (u2) body - NODE_CFUNC
|
187
|
-
* | |- (u1) cfnc - wrapper function to call
|
188
|
-
* | |- (u2) argc - function arity
|
189
|
-
* +- (u3) noex - NOEX_PUBLIC
|
190
|
-
*
|
191
|
-
* When the wrapper function is called, last_class is set to the origin
|
192
|
-
* class found in the FBODY node. So that the method data will be
|
193
|
-
* accessible, and so last_class will point to klass and not to our MEMO
|
194
|
-
* node, it is necessary to "fix" the current frame.
|
195
|
-
*
|
196
|
-
* Pre-YARV, this means we duplicate the current frame and set last_class:
|
197
|
-
*
|
198
|
-
* ruby_frame
|
199
|
-
* |- last_class - klass
|
200
|
-
* |- prev
|
201
|
-
* | |- last_class - NODE_MEMO
|
202
|
-
* | | |- (u1) cfnc - actual C function to call
|
203
|
-
* | | |- (u2) rval - stored data
|
204
|
-
* | | +- (u3) 0
|
205
|
-
* | |- prev - the real previous frame
|
206
|
-
* | +- ...
|
207
|
-
* +- ...
|
208
|
-
*
|
209
|
-
* The method data is then accessible via
|
210
|
-
* ruby_frame->prev->last_class->rval.
|
211
|
-
*
|
212
|
-
* On YARV, the current frame is not duplicated; rather, the method data
|
213
|
-
* is placed on the stack and is referenced by one of the unused members
|
214
|
-
* of the control frame (the program counter):
|
215
|
-
*
|
216
|
-
* ruby_current_thread->cfp
|
217
|
-
* |- pc - NODE_MEMO
|
218
|
-
* | |- (u1) cfnc - actual C function to call
|
219
|
-
* | |- (u2) rval - stored data
|
220
|
-
* | +- (u3) 0
|
221
|
-
* |- method_class - klass
|
222
|
-
* +- ...
|
223
|
-
*
|
224
|
-
*/
|
225
|
-
void define_method_with_data(
|
226
|
-
VALUE klass, ID id, VALUE (*cfunc)(ANYARGS), int arity, VALUE data)
|
227
|
-
{
|
228
|
-
/* TODO: origin should have #to_s and #inspect methods defined */
|
229
|
-
#ifdef HAVE_RB_CLASS_BOOT
|
230
|
-
VALUE origin = rb_class_boot(klass);
|
231
|
-
#else
|
232
|
-
VALUE origin = rb_class_new(klass);
|
233
|
-
#endif
|
234
|
-
NODE * node;
|
235
|
-
|
236
|
-
VALUE (*data_wrapper)(ANYARGS);
|
237
|
-
switch(arity)
|
238
|
-
{
|
239
|
-
#ruby <<END
|
240
|
-
(0..MAX_ARGS).each do |i|
|
241
|
-
puts <<-END
|
242
|
-
case #{i}: data_wrapper = RUBY_METHOD_FUNC(data_wrapper_#{i}); break;
|
243
|
-
END
|
244
|
-
end
|
245
|
-
nil
|
246
|
-
END
|
247
|
-
case -1: data_wrapper = RUBY_METHOD_FUNC(data_wrapper_m1); break;
|
248
|
-
default: rb_raise(rb_eArgError, "unsupported arity %d", arity);
|
249
|
-
}
|
250
|
-
|
251
|
-
FL_SET(origin, FL_SINGLETON);
|
252
|
-
rb_singleton_class_attached(origin, klass);
|
253
|
-
rb_name_class(origin, SYM2ID(rb_class_name(klass)));
|
254
|
-
|
255
|
-
RBASIC(origin)->klass = (VALUE)NEW_NODE(NODE_MEMO, cfunc, data, 0);
|
256
|
-
|
257
|
-
#ifdef RUBY_VM
|
258
|
-
/* YARV */
|
259
|
-
node = NEW_FBODY(
|
260
|
-
NEW_METHOD(
|
261
|
-
NEW_CFUNC(data_wrapper, arity),
|
262
|
-
origin,
|
263
|
-
NOEX_PUBLIC),
|
264
|
-
id);
|
265
|
-
st_insert(RCLASS_M_TBL(klass), id, (st_data_t)node);
|
266
|
-
#else
|
267
|
-
/* pre-YARV */
|
268
|
-
node = NEW_FBODY(
|
269
|
-
NEW_CFUNC(data_wrapper, arity),
|
270
|
-
id,
|
271
|
-
origin);
|
272
|
-
rb_add_method(klass, id, node, NOEX_PUBLIC);
|
273
|
-
#endif
|
274
|
-
}
|
275
|
-
|
276
|
-
VALUE get_method_data()
|
277
|
-
{
|
278
|
-
return data_memo_node()->nd_rval;
|
279
|
-
}
|
280
|
-
|
281
|
-
#else /* HAVE_RUBINIUS */
|
282
|
-
|
283
|
-
void define_method_with_data(
|
284
|
-
VALUE klass, ID id, VALUE (*cfunc)(ANYARGS), int arity, VALUE data)
|
285
|
-
{
|
286
|
-
rb_raise(rb_eNotImpError, "Not implemented: define_method_with_data");
|
287
|
-
}
|
288
|
-
|
289
|
-
VALUE get_method_data()
|
290
|
-
{
|
291
|
-
rb_raise(rb_eNotImpError, "Not implemented: get_method_data");
|
292
|
-
}
|
293
|
-
|
294
|
-
#endif
|
data/ext/method_data.h
DELETED