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 CHANGED
@@ -1 +1 @@
1
- 0.2.4
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
- VALUE v = ULONG2NUM((unsigned long)closure->function_ptr);
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 = STR2CSTR(name_v);
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 %d)",
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 = STR2CSTR(name_v);
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
- define_method_with_data(
1449
- klass, rb_intern(name), RUBY_METHOD_FUNC(closure->function_ptr),
1450
- arity, closure_v);
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
- hash: 31
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
- hash: 3
79
- segments:
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
- hash: 3
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.7.2
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
@@ -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
@@ -1,11 +0,0 @@
1
- #ifndef METHOD_DATA_H
2
- #define METHOD_DATA_H
3
-
4
- #include <ruby.h>
5
-
6
- void define_method_with_data(
7
- VALUE klass, ID id, VALUE (*cfunc)(ANYARGS), int arity, VALUE data);
8
-
9
- VALUE get_method_data();
10
-
11
- #endif // METHOD_DATA_H