fastruby 0.0.5 → 0.0.6
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/CHANGELOG +2 -0
- data/README +18 -2
- data/Rakefile +1 -1
- data/lib/fastruby/builder.rb +144 -20
- data/lib/fastruby/cache/cache.rb +86 -0
- data/lib/fastruby/custom_require.rb +3 -0
- data/lib/fastruby/exceptions.rb +10 -0
- data/lib/fastruby/fastruby_sexp.rb +25 -0
- data/lib/fastruby/getlocals.rb +2 -2
- data/lib/fastruby/object.rb +57 -268
- data/lib/fastruby/set_tree.rb +61 -0
- data/lib/fastruby/sexp_extension.rb +37 -0
- data/lib/fastruby/translator.rb +748 -287
- data/lib/fastruby.rb +12 -2
- metadata +8 -4
data/lib/fastruby/translator.rb
CHANGED
@@ -18,34 +18,32 @@ you should have received a copy of the gnu general public license
|
|
18
18
|
along with fastruby. if not, see <http://www.gnu.org/licenses/>.
|
19
19
|
|
20
20
|
=end
|
21
|
-
require "rubygems"
|
22
|
-
require "inline"
|
23
21
|
require "set"
|
24
22
|
require "fastruby/method_extension"
|
23
|
+
require "fastruby/set_tree"
|
24
|
+
require "fastruby/exceptions"
|
25
|
+
require "rubygems"
|
26
|
+
require "sexp"
|
25
27
|
|
26
28
|
module FastRuby
|
27
29
|
class Context
|
28
|
-
|
29
|
-
class UnwindFastrubyFrame < Exception
|
30
|
-
def initialize(ex,target_frame,return_value)
|
31
|
-
@ex = ex
|
32
|
-
@target_frame = target_frame
|
33
|
-
@return_value = return_value
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
30
|
attr_accessor :infer_lvar_map
|
38
31
|
attr_accessor :alt_method_name
|
39
32
|
attr_accessor :locals
|
40
33
|
attr_accessor :options
|
41
34
|
attr_accessor :infer_self
|
35
|
+
attr_accessor :snippet_hash
|
36
|
+
attr_reader :no_cache
|
37
|
+
attr_reader :init_extra
|
42
38
|
attr_reader :extra_code
|
43
39
|
attr_reader :yield_signature
|
44
40
|
|
45
41
|
def initialize(common_func = true)
|
46
42
|
@infer_lvar_map = Hash.new
|
43
|
+
@no_cache = false
|
47
44
|
@extra_code = ""
|
48
45
|
@options = {}
|
46
|
+
@init_extra = Array.new
|
49
47
|
@frame_struct = "struct {
|
50
48
|
void* parent_frame;
|
51
49
|
void* target_frame;
|
@@ -62,9 +60,20 @@ module FastRuby
|
|
62
60
|
void* block_function_param;
|
63
61
|
}"
|
64
62
|
|
63
|
+
|
65
64
|
extra_code << '#include "node.h"
|
66
65
|
'
|
67
66
|
|
67
|
+
ruby_code = "
|
68
|
+
$LOAD_PATH << #{FastRuby.fastruby_load_path.inspect}
|
69
|
+
require #{FastRuby.fastruby_script_path.inspect}
|
70
|
+
"
|
71
|
+
|
72
|
+
init_extra << "
|
73
|
+
rb_eval_string(#{ruby_code.inspect});
|
74
|
+
"
|
75
|
+
|
76
|
+
@common_func = common_func
|
68
77
|
if common_func
|
69
78
|
extra_code << "static VALUE _rb_gvar_set(void* ge,VALUE value) {
|
70
79
|
rb_gvar_set((struct global_entry*)ge,value);
|
@@ -72,6 +81,10 @@ module FastRuby
|
|
72
81
|
}
|
73
82
|
"
|
74
83
|
|
84
|
+
extra_code << "static VALUE re_yield(int argc, VALUE* argv, VALUE param, VALUE _parent_frame) {
|
85
|
+
return rb_yield_splat(rb_ary_new4(argc,argv));
|
86
|
+
}"
|
87
|
+
|
75
88
|
extra_code << "static VALUE _rb_ivar_set(VALUE recv,ID idvar, VALUE value) {
|
76
89
|
rb_ivar_set(recv,idvar,value);
|
77
90
|
return value;
|
@@ -82,6 +95,11 @@ module FastRuby
|
|
82
95
|
*destination = value;
|
83
96
|
return value;
|
84
97
|
}
|
98
|
+
|
99
|
+
/*
|
100
|
+
#{caller.join("\n")}
|
101
|
+
*/
|
102
|
+
|
85
103
|
"
|
86
104
|
end
|
87
105
|
end
|
@@ -125,6 +143,8 @@ module FastRuby
|
|
125
143
|
other_call_tree = call_tree.dup
|
126
144
|
other_call_tree[1] = s(:lvar, :arg)
|
127
145
|
|
146
|
+
mname = call_tree[2]
|
147
|
+
|
128
148
|
call_args_tree = call_tree[3]
|
129
149
|
|
130
150
|
caller_code = nil
|
@@ -135,8 +155,6 @@ module FastRuby
|
|
135
155
|
mobject = nil
|
136
156
|
len = nil
|
137
157
|
|
138
|
-
convention = :ruby
|
139
|
-
|
140
158
|
extra_inference = {}
|
141
159
|
|
142
160
|
if recvtype
|
@@ -153,10 +171,7 @@ module FastRuby
|
|
153
171
|
end
|
154
172
|
end
|
155
173
|
|
156
|
-
convention = nil
|
157
|
-
|
158
174
|
if recvtype.respond_to? :fastruby_method and inference_complete
|
159
|
-
|
160
175
|
method_tree = nil
|
161
176
|
begin
|
162
177
|
method_tree = recvtype.instance_method(call_tree[2]).fastruby.tree
|
@@ -178,24 +193,8 @@ module FastRuby
|
|
178
193
|
extra_inference[yield_args[i]] = yield_signature[i]
|
179
194
|
end
|
180
195
|
end
|
181
|
-
|
182
|
-
convention = :fastruby
|
183
|
-
else
|
184
|
-
mobject = recvtype.instance_method(call_tree[2])
|
185
|
-
convention = :cruby
|
186
196
|
end
|
187
|
-
else
|
188
|
-
mobject = recvtype.instance_method(call_tree[2])
|
189
|
-
convention = :cruby
|
190
|
-
end
|
191
|
-
|
192
|
-
address = getaddress(mobject)
|
193
|
-
len = getlen(mobject)
|
194
|
-
|
195
|
-
unless address
|
196
|
-
convention = :ruby
|
197
197
|
end
|
198
|
-
|
199
198
|
end
|
200
199
|
|
201
200
|
anonymous_impl = tree[3]
|
@@ -238,7 +237,19 @@ module FastRuby
|
|
238
237
|
end
|
239
238
|
end
|
240
239
|
|
241
|
-
|
240
|
+
|
241
|
+
if not args_tree
|
242
|
+
str_arg_initialization = ""
|
243
|
+
elsif args_tree.first == :lasgn
|
244
|
+
str_arg_initialization = "plocals->#{args_tree[1]} = arg;"
|
245
|
+
elsif args_tree.first == :masgn
|
246
|
+
arguments = args_tree[1][1..-1].map(&:last)
|
247
|
+
|
248
|
+
(0..arguments.size-1).each do |i|
|
249
|
+
str_arg_initialization << "plocals->#{arguments[i]} = rb_ary_entry(arg,#{i});\n"
|
250
|
+
end
|
251
|
+
end
|
252
|
+
rb_funcall_caller_code = nil
|
242
253
|
|
243
254
|
if call_args_tree.size > 1
|
244
255
|
|
@@ -247,12 +258,12 @@ module FastRuby
|
|
247
258
|
|
248
259
|
str_recv = "plocals->self" unless recv_tree
|
249
260
|
|
250
|
-
|
261
|
+
rb_funcall_caller_code = proc { |name| "
|
251
262
|
static VALUE #{name}(VALUE param) {
|
252
263
|
// call to #{call_tree[2]}
|
253
264
|
|
254
265
|
#{str_lvar_initialization}
|
255
|
-
return rb_funcall(#{str_recv}, #{call_tree[2]
|
266
|
+
return rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, #{call_args_tree.size-1}, #{str_called_code_args});
|
256
267
|
}
|
257
268
|
"
|
258
269
|
}
|
@@ -261,31 +272,18 @@ module FastRuby
|
|
261
272
|
str_recv = to_c recv_tree
|
262
273
|
str_recv = "plocals->self" unless recv_tree
|
263
274
|
|
264
|
-
|
275
|
+
rb_funcall_caller_code = proc { |name| "
|
265
276
|
static VALUE #{name}(VALUE param) {
|
266
277
|
// call to #{call_tree[2]}
|
267
278
|
#{str_lvar_initialization}
|
268
|
-
return rb_funcall(#{str_recv}, #{call_tree[2]
|
279
|
+
return rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, 0);
|
269
280
|
}
|
270
281
|
"
|
271
282
|
}
|
272
283
|
end
|
273
284
|
|
274
|
-
if not args_tree
|
275
|
-
str_arg_initialization = ""
|
276
|
-
elsif args_tree.first == :lasgn
|
277
|
-
str_arg_initialization = "plocals->#{args_tree[1]} = arg;"
|
278
|
-
elsif args_tree.first == :masgn
|
279
|
-
arguments = args_tree[1][1..-1].map(&:last)
|
280
|
-
|
281
|
-
(0..arguments.size-1).each do |i|
|
282
|
-
str_arg_initialization << "plocals->#{arguments[i]} = rb_ary_entry(arg,#{i});\n"
|
283
|
-
end
|
284
|
-
end
|
285
|
-
|
286
|
-
str_arg_initialization
|
287
285
|
|
288
|
-
|
286
|
+
rb_funcall_block_code = proc { |name| "
|
289
287
|
static VALUE #{name}(VALUE arg, VALUE _plocals) {
|
290
288
|
// block for call to #{call_tree[2]}
|
291
289
|
VALUE last_expression = Qnil;
|
@@ -308,15 +306,15 @@ module FastRuby
|
|
308
306
|
}
|
309
307
|
|
310
308
|
VALUE ex = rb_funcall(
|
311
|
-
|
312
|
-
#{:new
|
309
|
+
#{literal_value FastRuby::Context::UnwindFastrubyFrame},
|
310
|
+
#{intern_num :new},
|
313
311
|
3,
|
314
312
|
pframe->exception,
|
315
313
|
LONG2FIX(pframe->target_frame),
|
316
314
|
pframe->return_value
|
317
315
|
);
|
318
316
|
|
319
|
-
rb_funcall(plocals->self, #{:raise
|
317
|
+
rb_funcall(plocals->self, #{intern_num :raise}, 1, ex);
|
320
318
|
}
|
321
319
|
return frame.return_value;
|
322
320
|
}
|
@@ -330,21 +328,18 @@ module FastRuby
|
|
330
328
|
"
|
331
329
|
}
|
332
330
|
|
333
|
-
protected_block("rb_iterate(#{anonymous_function(&caller_code)}, (VALUE)pframe, #{anonymous_function(&block_code)}, (VALUE)plocals)", true)
|
334
|
-
|
335
|
-
elsif convention == :fastruby
|
336
331
|
|
337
|
-
|
332
|
+
fastruby_str_arg_initialization = ""
|
338
333
|
|
339
334
|
if not args_tree
|
340
|
-
|
335
|
+
fastruby_str_arg_initialization = ""
|
341
336
|
elsif args_tree.first == :lasgn
|
342
|
-
|
337
|
+
fastruby_str_arg_initialization = "plocals->#{args_tree[1]} = argv[0];"
|
343
338
|
elsif args_tree.first == :masgn
|
344
339
|
arguments = args_tree[1][1..-1].map(&:last)
|
345
340
|
|
346
341
|
(0..arguments.size-1).each do |i|
|
347
|
-
|
342
|
+
fastruby_str_arg_initialization << "plocals->#{arguments[i]} = #{i} < argc ? argv[#{i}] : Qnil;\n"
|
348
343
|
end
|
349
344
|
end
|
350
345
|
|
@@ -380,7 +375,7 @@ module FastRuby
|
|
380
375
|
|
381
376
|
}
|
382
377
|
|
383
|
-
#{
|
378
|
+
#{fastruby_str_arg_initialization}
|
384
379
|
#{str_impl}
|
385
380
|
|
386
381
|
return last_expression;
|
@@ -388,16 +383,17 @@ module FastRuby
|
|
388
383
|
"
|
389
384
|
}
|
390
385
|
|
391
|
-
|
392
386
|
str_recv = "plocals->self"
|
393
387
|
|
394
388
|
if recv_tree
|
395
389
|
str_recv = to_c recv_tree
|
396
390
|
end
|
397
391
|
|
392
|
+
caller_code = nil
|
393
|
+
convention_global_name = add_global_name("int",0)
|
394
|
+
|
398
395
|
if call_args_tree.size > 1
|
399
|
-
value_cast = ( ["VALUE"]*(call_tree[3].size) ).join(",")
|
400
|
-
value_cast = value_cast + ", VALUE, VALUE" if convention == :fastruby
|
396
|
+
value_cast = ( ["VALUE"]*(call_tree[3].size) ).join(",") + ", VALUE, VALUE"
|
401
397
|
|
402
398
|
str_called_code_args = call_tree[3][1..-1].map{|subtree| to_c subtree}.join(",")
|
403
399
|
|
@@ -411,7 +407,7 @@ module FastRuby
|
|
411
407
|
|
412
408
|
// call to #{call_tree[2]}
|
413
409
|
|
414
|
-
return ((VALUE(*)(#{value_cast}))
|
410
|
+
return ((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,call_tree,inference_complete,convention_global_name)})(#{str_recv}, (VALUE)&block, (VALUE)pframe, #{str_called_code_args});
|
415
411
|
}
|
416
412
|
"
|
417
413
|
}
|
@@ -427,14 +423,21 @@ module FastRuby
|
|
427
423
|
|
428
424
|
// call to #{call_tree[2]}
|
429
425
|
|
430
|
-
return ((VALUE(*)(VALUE,VALUE,VALUE))
|
426
|
+
return ((VALUE(*)(VALUE,VALUE,VALUE))#{encode_address(recvtype,signature,mname,call_tree,inference_complete,convention_global_name)})(#{str_recv}, (VALUE)&block, (VALUE)pframe);
|
431
427
|
}
|
432
428
|
"
|
433
429
|
}
|
434
430
|
end
|
435
431
|
|
436
|
-
|
437
|
-
|
432
|
+
inline_block "
|
433
|
+
if (#{convention_global_name}) {
|
434
|
+
return #{anonymous_function(&caller_code)}((VALUE)plocals, (VALUE)pframe);
|
435
|
+
} else {
|
436
|
+
return #{
|
437
|
+
protected_block("rb_iterate(#{anonymous_function(&rb_funcall_caller_code)}, (VALUE)pframe, #{anonymous_function(&rb_funcall_block_code)}, (VALUE)plocals)", true)
|
438
|
+
};
|
439
|
+
}
|
440
|
+
"
|
438
441
|
end
|
439
442
|
|
440
443
|
def to_c_yield(tree)
|
@@ -478,7 +481,7 @@ module FastRuby
|
|
478
481
|
anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){})"
|
479
482
|
end
|
480
483
|
|
481
|
-
protected_block(ret,
|
484
|
+
protected_block(ret, false)
|
482
485
|
end
|
483
486
|
|
484
487
|
def to_c_block(tree)
|
@@ -518,7 +521,7 @@ module FastRuby
|
|
518
521
|
else
|
519
522
|
inline_block("
|
520
523
|
pframe->target_frame = (void*)-1;
|
521
|
-
pframe->exception =
|
524
|
+
pframe->exception = #{literal_value LocalJumpError.exception};
|
522
525
|
longjmp(pframe->jmp,1);
|
523
526
|
return Qnil;
|
524
527
|
")
|
@@ -532,7 +535,7 @@ module FastRuby
|
|
532
535
|
else
|
533
536
|
inline_block("
|
534
537
|
pframe->target_frame = (void*)-1;
|
535
|
-
pframe->exception =
|
538
|
+
pframe->exception = #{literal_value LocalJumpError.exception};
|
536
539
|
longjmp(pframe->jmp,1);
|
537
540
|
return Qnil;
|
538
541
|
")
|
@@ -541,7 +544,7 @@ module FastRuby
|
|
541
544
|
end
|
542
545
|
|
543
546
|
def to_c_lit(tree)
|
544
|
-
|
547
|
+
literal_value tree[1]
|
545
548
|
end
|
546
549
|
|
547
550
|
def to_c_nil(tree)
|
@@ -549,7 +552,7 @@ module FastRuby
|
|
549
552
|
end
|
550
553
|
|
551
554
|
def to_c_str(tree)
|
552
|
-
|
555
|
+
literal_value tree[1]
|
553
556
|
end
|
554
557
|
|
555
558
|
def to_c_hash(tree)
|
@@ -597,24 +600,24 @@ module FastRuby
|
|
597
600
|
inline_block "
|
598
601
|
// set constant #{tree[1].to_s}
|
599
602
|
VALUE val = #{to_c tree[2]};
|
600
|
-
rb_const_set(rb_cObject, #{tree[1]
|
603
|
+
rb_const_set(rb_cObject, #{intern_num tree[1]}, val);
|
601
604
|
return val;
|
602
605
|
"
|
603
|
-
elsif tree[1].instance_of?
|
606
|
+
elsif tree[1].instance_of? FastRuby::FastRubySexp
|
604
607
|
|
605
608
|
if tree[1].node_type == :colon2
|
606
609
|
inline_block "
|
607
610
|
// set constant #{tree[1].to_s}
|
608
611
|
VALUE val = #{to_c tree[2]};
|
609
612
|
VALUE klass = #{to_c tree[1][1]};
|
610
|
-
rb_const_set(klass, #{tree[1][2]
|
613
|
+
rb_const_set(klass, #{intern_num tree[1][2]}, val);
|
611
614
|
return val;
|
612
615
|
"
|
613
616
|
elsif tree[1].node_type == :colon3
|
614
617
|
inline_block "
|
615
618
|
// set constant #{tree[1].to_s}
|
616
619
|
VALUE val = #{to_c tree[2]};
|
617
|
-
rb_const_set(rb_cObject, #{tree[1][1]
|
620
|
+
rb_const_set(rb_cObject, #{intern_num tree[1][1]}, val);
|
618
621
|
return val;
|
619
622
|
"
|
620
623
|
end
|
@@ -652,11 +655,165 @@ module FastRuby
|
|
652
655
|
end
|
653
656
|
|
654
657
|
def to_c_const(tree)
|
655
|
-
"rb_const_get(CLASS_OF(plocals->self), #{tree[1]
|
658
|
+
"rb_const_get(CLASS_OF(plocals->self), #{intern_num(tree[1])})"
|
656
659
|
end
|
657
660
|
|
658
661
|
def to_c_defn(tree)
|
659
|
-
|
662
|
+
|
663
|
+
method_name = tree[1]
|
664
|
+
args_tree = tree[2]
|
665
|
+
|
666
|
+
global_klass_variable = add_global_name("VALUE", "Qnil");
|
667
|
+
|
668
|
+
hash = Hash.new
|
669
|
+
value_cast = ( ["VALUE"]*(args_tree.size+2) ).join(",")
|
670
|
+
|
671
|
+
strmethodargs = ""
|
672
|
+
strmethodargs_class = (["self"] + args_tree[1..-1]).map{|arg| "CLASS_OF(#{arg.to_s})"}.join(",")
|
673
|
+
|
674
|
+
if args_tree.size > 1
|
675
|
+
strmethodargs = "self,block,(VALUE)&frame,#{args_tree[1..-1].map(&:to_s).join(",") }"
|
676
|
+
else
|
677
|
+
strmethodargs = "self,block,(VALUE)&frame"
|
678
|
+
end
|
679
|
+
|
680
|
+
strmethod_signature = (["self"] + args_tree[1..-1]).map { |arg|
|
681
|
+
"sprintf(method_name+strlen(method_name), \"%lu\", FIX2LONG(rb_obj_id(CLASS_OF(#{arg}))));\n"
|
682
|
+
}.join
|
683
|
+
|
684
|
+
anonymous_method_name = anonymous_function{ |anonymous_method_name| "VALUE #{anonymous_method_name}(#{(["self"]+args_tree[1..-1]).map{|arg| "VALUE #{arg}" }.join(",")}) {
|
685
|
+
|
686
|
+
VALUE klass = #{global_klass_variable};
|
687
|
+
char method_name[0x100];
|
688
|
+
|
689
|
+
method_name[0] = '_';
|
690
|
+
method_name[1] = 0;
|
691
|
+
|
692
|
+
sprintf(method_name+1, \"#{method_name}\");
|
693
|
+
#{strmethod_signature}
|
694
|
+
|
695
|
+
NODE* body;
|
696
|
+
ID id;
|
697
|
+
|
698
|
+
id = rb_intern(method_name);
|
699
|
+
body = rb_method_node(klass,id);
|
700
|
+
|
701
|
+
if (body == 0) {
|
702
|
+
VALUE argv_class[] = {#{strmethodargs_class} };
|
703
|
+
VALUE signature = rb_ary_new4(#{args_tree.size},argv_class);
|
704
|
+
|
705
|
+
VALUE mobject = rb_funcall(#{global_klass_variable}, #{intern_num :build}, 2, signature,rb_str_new2(#{method_name.to_s.inspect}));
|
706
|
+
|
707
|
+
struct METHOD {
|
708
|
+
VALUE klass, rklass;
|
709
|
+
VALUE recv;
|
710
|
+
ID id, oid;
|
711
|
+
int safe_level;
|
712
|
+
NODE *body;
|
713
|
+
};
|
714
|
+
|
715
|
+
struct METHOD *data;
|
716
|
+
Data_Get_Struct(mobject, struct METHOD, data);
|
717
|
+
body = data->body;
|
718
|
+
|
719
|
+
if (body == 0) {
|
720
|
+
rb_raise(rb_eRuntimeError,\"method not found after build: '%s'\", method_name);
|
721
|
+
}
|
722
|
+
}
|
723
|
+
|
724
|
+
if (nd_type(body) == NODE_CFUNC) {
|
725
|
+
struct {
|
726
|
+
void* parent_frame;
|
727
|
+
void* target_frame;
|
728
|
+
void* plocals;
|
729
|
+
jmp_buf jmp;
|
730
|
+
VALUE return_value;
|
731
|
+
VALUE exception;
|
732
|
+
int rescue;
|
733
|
+
} frame;
|
734
|
+
|
735
|
+
frame.target_frame = 0;
|
736
|
+
frame.parent_frame = 0;
|
737
|
+
frame.rescue = 0;
|
738
|
+
frame.exception = Qnil;
|
739
|
+
frame.return_value = Qnil;
|
740
|
+
|
741
|
+
int argc = body->nd_argc;
|
742
|
+
|
743
|
+
VALUE block = Qfalse;
|
744
|
+
|
745
|
+
if (rb_block_given_p()) {
|
746
|
+
struct {
|
747
|
+
void *block_function_address;
|
748
|
+
void *block_function_param;
|
749
|
+
} block_struct;
|
750
|
+
|
751
|
+
block_struct.block_function_address = re_yield;
|
752
|
+
block_struct.block_function_param = 0;
|
753
|
+
|
754
|
+
block = (VALUE)&block_struct;
|
755
|
+
}
|
756
|
+
|
757
|
+
int aux = setjmp(frame.jmp);
|
758
|
+
if (aux != 0) {
|
759
|
+
if (frame.target_frame == (void*)-1) {
|
760
|
+
rb_funcall(self, #{intern_num :raise}, 1, frame.exception);
|
761
|
+
}
|
762
|
+
|
763
|
+
if (frame.target_frame != &frame) {
|
764
|
+
VALUE ex = rb_funcall(
|
765
|
+
#{literal_value FastRuby::Context::UnwindFastrubyFrame},
|
766
|
+
#{intern_num :new},
|
767
|
+
3,
|
768
|
+
frame.exception,
|
769
|
+
LONG2FIX(frame.target_frame),
|
770
|
+
frame.return_value
|
771
|
+
);
|
772
|
+
|
773
|
+
rb_funcall(self, #{intern_num :raise}, 1, ex);
|
774
|
+
}
|
775
|
+
|
776
|
+
return Qnil;
|
777
|
+
}
|
778
|
+
|
779
|
+
if (argc == #{args_tree.size+1}) {
|
780
|
+
return ((VALUE(*)(#{value_cast}))body->nd_cfnc)(#{strmethodargs});
|
781
|
+
} else if (argc == -1) {
|
782
|
+
VALUE argv[] = {#{(["block,(VALUE)&frame"]+args_tree[1..-1]).map(&:to_s).join(",")} };
|
783
|
+
return ((VALUE(*)(int,VALUE*,VALUE))body->nd_cfnc)(#{args_tree.size},argv,self);
|
784
|
+
} else if (argc == -2) {
|
785
|
+
VALUE argv[] = {#{(["block,(VALUE)&frame"]+args_tree[1..-1]).map(&:to_s).join(",")} };
|
786
|
+
return ((VALUE(*)(VALUE,VALUE))body->nd_cfnc)(self, rb_ary_new4(#{args_tree.size},argv));
|
787
|
+
} else {
|
788
|
+
rb_raise(rb_eArgError, \"wrong number of arguments (#{args_tree.size-1} for %d)\", argc);
|
789
|
+
}
|
790
|
+
}
|
791
|
+
|
792
|
+
return Qnil;
|
793
|
+
}"
|
794
|
+
}
|
795
|
+
|
796
|
+
alt_options = options.dup
|
797
|
+
|
798
|
+
alt_options.delete(:self)
|
799
|
+
alt_options.delete(:main)
|
800
|
+
|
801
|
+
inline_block "
|
802
|
+
#{global_klass_variable} = plocals->self;
|
803
|
+
|
804
|
+
// set tree
|
805
|
+
rb_funcall(#{literal_value FastRuby}, #{intern_num :set_tree}, 5,
|
806
|
+
#{global_klass_variable},
|
807
|
+
rb_str_new2(#{method_name.to_s.inspect}),
|
808
|
+
#{literal_value tree},
|
809
|
+
#{literal_value snippet_hash},
|
810
|
+
#{literal_value alt_options}
|
811
|
+
|
812
|
+
);
|
813
|
+
|
814
|
+
rb_define_method(plocals->self, #{method_name.to_s.inspect}, #{anonymous_method_name}, #{args_tree.size-1} );
|
815
|
+
"
|
816
|
+
|
660
817
|
end
|
661
818
|
|
662
819
|
def to_c_defs(tree)
|
@@ -665,6 +822,7 @@ module FastRuby
|
|
665
822
|
tmp = FastRuby.build_defs(tree)
|
666
823
|
|
667
824
|
extra_code << tmp[0]
|
825
|
+
@init_extra = @init_extra + tmp[2]
|
668
826
|
|
669
827
|
inline_block "
|
670
828
|
rb_define_singleton_method(#{to_c tree[1]}, \"#{tree[2].to_s}\", (void*)#{tmp[1]}, #{args_tree.size-1});
|
@@ -686,15 +844,15 @@ module FastRuby
|
|
686
844
|
elsif nt == :lvar
|
687
845
|
'rb_str_new2("local-variable")'
|
688
846
|
elsif nt == :gvar
|
689
|
-
"rb_gvar_defined((struct global_entry*)
|
847
|
+
"rb_gvar_defined((struct global_entry*)#{global_entry(tree[1][1])}) ? #{literal_value "global-variable"} : Qnil"
|
690
848
|
elsif nt == :const
|
691
|
-
"rb_const_defined(rb_cObject, #{tree[1][1]
|
849
|
+
"rb_const_defined(rb_cObject, #{intern_num tree[1][1]}) ? #{literal_value "constant"} : Qnil"
|
692
850
|
elsif nt == :call
|
693
|
-
"rb_method_node(CLASS_OF(#{to_c tree[1][1]}), #{tree[1][2]
|
851
|
+
"rb_method_node(CLASS_OF(#{to_c tree[1][1]}), #{intern_num tree[1][2]}) ? #{literal_value "method"} : Qnil"
|
694
852
|
elsif nt == :yield
|
695
|
-
"rb_block_given_p() ? #{"yield"
|
853
|
+
"rb_block_given_p() ? #{literal_value "yield"} : Qnil"
|
696
854
|
elsif nt == :ivar
|
697
|
-
"rb_ivar_defined(plocals->self,#{tree[1][1]
|
855
|
+
"rb_ivar_defined(plocals->self,#{intern_num tree[1][1]}) ? #{literal_value "instance-variable"} : Qnil"
|
698
856
|
elsif nt == :attrset or
|
699
857
|
nt == :op_asgn1 or
|
700
858
|
nt == :op_asgn2 or
|
@@ -710,9 +868,9 @@ module FastRuby
|
|
710
868
|
nt == :cdecl or
|
711
869
|
nt == :cvdecl or
|
712
870
|
nt == :cvasgn
|
713
|
-
"assignment"
|
871
|
+
literal_value "assignment"
|
714
872
|
else
|
715
|
-
"expression"
|
873
|
+
literal_value "expression"
|
716
874
|
end
|
717
875
|
end
|
718
876
|
|
@@ -726,6 +884,27 @@ module FastRuby
|
|
726
884
|
#{@locals.map{|l| "VALUE #{l};\n"}.join}
|
727
885
|
#{args_tree[1..-1].map{|arg| "VALUE #{arg};\n"}.join};
|
728
886
|
}"
|
887
|
+
|
888
|
+
if @common_func
|
889
|
+
init_extra << "
|
890
|
+
#{@frame_struct} frame;
|
891
|
+
#{@locals_struct} locals;
|
892
|
+
|
893
|
+
locals.return_value = Qnil;
|
894
|
+
locals.pframe = &frame;
|
895
|
+
locals.self = rb_cObject;
|
896
|
+
|
897
|
+
frame.target_frame = 0;
|
898
|
+
frame.plocals = (void*)&locals;
|
899
|
+
frame.return_value = Qnil;
|
900
|
+
frame.exception = Qnil;
|
901
|
+
frame.rescue = 0;
|
902
|
+
frame.last_error = Qnil;
|
903
|
+
|
904
|
+
typeof(&frame) pframe = &frame;
|
905
|
+
"
|
906
|
+
end
|
907
|
+
|
729
908
|
end
|
730
909
|
|
731
910
|
def to_c_method_defs(tree)
|
@@ -800,7 +979,7 @@ module FastRuby
|
|
800
979
|
|
801
980
|
int aux = setjmp(frame.jmp);
|
802
981
|
if (aux != 0) {
|
803
|
-
rb_funcall(self, #{:raise
|
982
|
+
rb_funcall(self, #{intern_num :raise}, 1, frame.exception);
|
804
983
|
}
|
805
984
|
|
806
985
|
|
@@ -809,39 +988,141 @@ module FastRuby
|
|
809
988
|
"
|
810
989
|
end
|
811
990
|
|
991
|
+
def add_main
|
992
|
+
if options[:main]
|
993
|
+
|
994
|
+
extra_code << "
|
995
|
+
static VALUE #{@alt_method_name}(VALUE self__);
|
996
|
+
static VALUE main_proc_call(VALUE self__, VALUE class_self_) {
|
997
|
+
#{@alt_method_name}(class_self_);
|
998
|
+
return Qnil;
|
999
|
+
}
|
1000
|
+
|
1001
|
+
"
|
1002
|
+
|
1003
|
+
init_extra << "
|
1004
|
+
{
|
1005
|
+
VALUE newproc = rb_funcall(rb_cObject,#{intern_num :new},0);
|
1006
|
+
rb_define_singleton_method(newproc, \"call\", main_proc_call, 1);
|
1007
|
+
rb_gv_set(\"$last_obj_proc\", newproc);
|
1008
|
+
|
1009
|
+
}
|
1010
|
+
"
|
1011
|
+
end
|
1012
|
+
end
|
1013
|
+
|
1014
|
+
def define_method_at_init(method_name, size, signature)
|
1015
|
+
init_extra << "
|
1016
|
+
{
|
1017
|
+
VALUE method_name = rb_funcall(
|
1018
|
+
#{literal_value FastRuby},
|
1019
|
+
#{intern_num :make_str_signature},
|
1020
|
+
2,
|
1021
|
+
#{literal_value method_name},
|
1022
|
+
#{literal_value signature}
|
1023
|
+
);
|
1024
|
+
|
1025
|
+
rb_define_method(#{to_c s(:gvar, :$class_self)}, RSTRING(method_name)->ptr, #{alt_method_name}, #{size});
|
1026
|
+
}
|
1027
|
+
"
|
1028
|
+
end
|
1029
|
+
|
812
1030
|
def to_c_method(tree)
|
813
1031
|
method_name = tree[1]
|
814
1032
|
args_tree = tree[2]
|
815
|
-
|
816
1033
|
impl_tree = tree[3][1]
|
817
1034
|
|
818
|
-
|
1035
|
+
if (options[:main])
|
1036
|
+
initialize_method_structs(args_tree)
|
819
1037
|
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
1038
|
+
strargs = if args_tree.size > 1
|
1039
|
+
"VALUE block, VALUE _parent_frame, #{args_tree[1..-1].map{|arg| "VALUE #{arg}" }.join(",") }"
|
1040
|
+
else
|
1041
|
+
"VALUE block, VALUE _parent_frame"
|
1042
|
+
end
|
825
1043
|
|
826
|
-
|
1044
|
+
ret = "VALUE #{@alt_method_name || method_name}() {
|
827
1045
|
|
828
|
-
|
1046
|
+
#{@locals_struct} locals;
|
1047
|
+
#{@locals_struct} *plocals = (void*)&locals;
|
1048
|
+
#{@frame_struct} frame;
|
1049
|
+
#{@frame_struct} *pframe;
|
829
1050
|
|
830
|
-
|
831
|
-
|
832
|
-
|
1051
|
+
frame.plocals = plocals;
|
1052
|
+
frame.parent_frame = 0;
|
1053
|
+
frame.return_value = Qnil;
|
1054
|
+
frame.target_frame = &frame;
|
1055
|
+
frame.exception = Qnil;
|
1056
|
+
frame.rescue = 0;
|
1057
|
+
|
1058
|
+
locals.pframe = &frame;
|
1059
|
+
|
1060
|
+
pframe = (void*)&frame;
|
1061
|
+
|
1062
|
+
VALUE last_expression = Qnil;
|
1063
|
+
|
1064
|
+
int aux = setjmp(pframe->jmp);
|
1065
|
+
if (aux != 0) {
|
1066
|
+
|
1067
|
+
if (pframe->target_frame == (void*)-2) {
|
1068
|
+
return pframe->return_value;
|
1069
|
+
}
|
1070
|
+
|
1071
|
+
if (pframe->target_frame != pframe) {
|
1072
|
+
// raise exception
|
1073
|
+
return Qnil;
|
1074
|
+
}
|
1075
|
+
|
1076
|
+
return plocals->return_value;
|
1077
|
+
}
|
1078
|
+
|
1079
|
+
locals.self = self;
|
1080
|
+
|
1081
|
+
#{args_tree[1..-1].map { |arg|
|
1082
|
+
"locals.#{arg} = #{arg};\n"
|
1083
|
+
}.join("") }
|
833
1084
|
|
834
|
-
pblock = (void*)block;
|
835
|
-
if (pblock) {
|
836
|
-
locals.block_function_address = pblock->block_function_address;
|
837
|
-
locals.block_function_param = (VALUE)pblock->block_function_param;
|
838
|
-
} else {
|
839
1085
|
locals.block_function_address = 0;
|
840
1086
|
locals.block_function_param = Qnil;
|
841
|
-
}
|
842
1087
|
|
843
|
-
|
844
|
-
|
1088
|
+
return #{to_c impl_tree};
|
1089
|
+
}"
|
1090
|
+
|
1091
|
+
add_main
|
1092
|
+
ret
|
1093
|
+
else
|
1094
|
+
|
1095
|
+
initialize_method_structs(args_tree)
|
1096
|
+
|
1097
|
+
strargs = if args_tree.size > 1
|
1098
|
+
"VALUE block, VALUE _parent_frame, #{args_tree[1..-1].map{|arg| "VALUE #{arg}" }.join(",") }"
|
1099
|
+
else
|
1100
|
+
"VALUE block, VALUE _parent_frame"
|
1101
|
+
end
|
1102
|
+
|
1103
|
+
ret = "VALUE #{@alt_method_name || method_name}(#{strargs}) {
|
1104
|
+
|
1105
|
+
#{func_frame}
|
1106
|
+
|
1107
|
+
#{args_tree[1..-1].map { |arg|
|
1108
|
+
"locals.#{arg} = #{arg};\n"
|
1109
|
+
}.join("") }
|
1110
|
+
|
1111
|
+
pblock = (void*)block;
|
1112
|
+
if (pblock) {
|
1113
|
+
locals.block_function_address = pblock->block_function_address;
|
1114
|
+
locals.block_function_param = (VALUE)pblock->block_function_param;
|
1115
|
+
} else {
|
1116
|
+
locals.block_function_address = 0;
|
1117
|
+
locals.block_function_param = Qnil;
|
1118
|
+
}
|
1119
|
+
|
1120
|
+
return #{to_c impl_tree};
|
1121
|
+
}"
|
1122
|
+
|
1123
|
+
add_main
|
1124
|
+
ret
|
1125
|
+
end
|
845
1126
|
end
|
846
1127
|
|
847
1128
|
def locals_accessor
|
@@ -849,33 +1130,33 @@ module FastRuby
|
|
849
1130
|
end
|
850
1131
|
|
851
1132
|
def to_c_gvar(tree)
|
852
|
-
"rb_gvar_get((struct global_entry*)
|
1133
|
+
"rb_gvar_get((struct global_entry*)#{global_entry(tree[1])})"
|
853
1134
|
end
|
854
1135
|
|
855
1136
|
def to_c_gasgn(tree)
|
856
|
-
"_rb_gvar_set((void*)
|
1137
|
+
"_rb_gvar_set((void*)#{global_entry(tree[1])}, #{to_c tree[2]})"
|
857
1138
|
end
|
858
1139
|
|
859
1140
|
def to_c_ivar(tree)
|
860
|
-
"rb_ivar_get(#{locals_accessor}self,#{tree[1]
|
1141
|
+
"rb_ivar_get(#{locals_accessor}self,#{intern_num tree[1]})"
|
861
1142
|
end
|
862
1143
|
|
863
1144
|
def to_c_iasgn(tree)
|
864
|
-
"_rb_ivar_set(#{locals_accessor}self,#{tree[1]
|
1145
|
+
"_rb_ivar_set(#{locals_accessor}self,#{intern_num tree[1]},#{to_c tree[2]})"
|
865
1146
|
end
|
866
1147
|
|
867
1148
|
def to_c_colon3(tree)
|
868
|
-
"rb_const_get_from(rb_cObject, #{tree[1]
|
1149
|
+
"rb_const_get_from(rb_cObject, #{intern_num tree[1]})"
|
869
1150
|
end
|
870
1151
|
def to_c_colon2(tree)
|
871
1152
|
inline_block "
|
872
1153
|
VALUE klass = #{to_c tree[1]};
|
873
1154
|
|
874
|
-
if (rb_is_const_id(#{tree[2]
|
1155
|
+
if (rb_is_const_id(#{intern_num tree[2]})) {
|
875
1156
|
switch (TYPE(klass)) {
|
876
1157
|
case T_CLASS:
|
877
1158
|
case T_MODULE:
|
878
|
-
return rb_const_get_from(klass, #{tree[2]
|
1159
|
+
return rb_const_get_from(klass, #{intern_num tree[2]});
|
879
1160
|
break;
|
880
1161
|
default:
|
881
1162
|
rb_raise(rb_eTypeError, \"%s is not a class/module\",
|
@@ -884,7 +1165,7 @@ module FastRuby
|
|
884
1165
|
}
|
885
1166
|
}
|
886
1167
|
else {
|
887
|
-
return rb_funcall(klass, #{tree[2]
|
1168
|
+
return rb_funcall(klass, #{intern_num tree[2]}, 0, 0);
|
888
1169
|
}
|
889
1170
|
|
890
1171
|
return Qnil;
|
@@ -898,7 +1179,7 @@ module FastRuby
|
|
898
1179
|
|
899
1180
|
verify_type_function = proc { |name| "
|
900
1181
|
static VALUE #{name}(VALUE arg) {
|
901
|
-
if (CLASS_OF(arg)!=#{klass
|
1182
|
+
if (CLASS_OF(arg)!=#{literal_value klass}) rb_raise(#{literal_value FastRuby::TypeMismatchAssignmentException}, \"Illegal assignment at runtime (type mismatch)\");
|
902
1183
|
return arg;
|
903
1184
|
}
|
904
1185
|
"
|
@@ -1010,7 +1291,7 @@ module FastRuby
|
|
1010
1291
|
|
1011
1292
|
return inline_block("
|
1012
1293
|
pframe->target_frame = (void*)-1;
|
1013
|
-
pframe->exception = rb_funcall(#{to_c args[1]}, #{:exception
|
1294
|
+
pframe->exception = rb_funcall(#{to_c args[1]}, #{intern_num :exception},0);
|
1014
1295
|
longjmp(pframe->jmp, 1);
|
1015
1296
|
return Qnil;
|
1016
1297
|
")
|
@@ -1047,144 +1328,164 @@ module FastRuby
|
|
1047
1328
|
end
|
1048
1329
|
end
|
1049
1330
|
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
rescue NoMethodError
|
1058
|
-
end
|
1331
|
+
if repass_var
|
1332
|
+
extraargs = ","+repass_var
|
1333
|
+
extraargs_signature = ",VALUE " + repass_var
|
1334
|
+
else
|
1335
|
+
extraargs = ""
|
1336
|
+
extraargs_signature = ""
|
1337
|
+
end
|
1059
1338
|
|
1060
|
-
if
|
1061
|
-
|
1062
|
-
|
1339
|
+
if argnum == 0
|
1340
|
+
value_cast = "VALUE,VALUE,VALUE"
|
1341
|
+
"((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(#{to_c recv}, Qfalse, (VALUE)pframe)"
|
1063
1342
|
else
|
1064
|
-
|
1065
|
-
|
1343
|
+
value_cast = ( ["VALUE"]*(args.size) ).join(",") + ",VALUE,VALUE"
|
1344
|
+
"((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(#{to_c recv}, Qfalse, (VALUE)pframe, #{strargs})"
|
1066
1345
|
end
|
1346
|
+
|
1347
|
+
else # else recvtype
|
1348
|
+
if argnum == 0
|
1349
|
+
protected_block("rb_funcall(#{to_c recv}, #{intern_num tree[2]}, 0)", false, repass_var)
|
1067
1350
|
else
|
1068
|
-
|
1069
|
-
convention = :cruby
|
1351
|
+
protected_block("rb_funcall(#{to_c recv}, #{intern_num tree[2]}, #{argnum}, #{strargs} )", false, repass_var)
|
1070
1352
|
end
|
1353
|
+
end # if recvtype
|
1354
|
+
end
|
1071
1355
|
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1356
|
+
def get_class_name(argument)
|
1357
|
+
if argument.instance_of? Symbol
|
1358
|
+
argument.to_s
|
1359
|
+
elsif argument.instance_of? FastRuby::FastRubySexp
|
1360
|
+
if argument[0] == :colon3
|
1361
|
+
get_class_name(argument[1])
|
1362
|
+
elsif argument[0] == :colon2
|
1363
|
+
get_class_name(argument[2])
|
1077
1364
|
end
|
1365
|
+
end
|
1366
|
+
end
|
1078
1367
|
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1368
|
+
def get_container_tree(argument)
|
1369
|
+
if argument.instance_of? Symbol
|
1370
|
+
s(:self)
|
1371
|
+
elsif argument.instance_of? FastRuby::FastRubySexp
|
1372
|
+
if argument[0] == :colon3
|
1373
|
+
s(:const, :Object)
|
1374
|
+
elsif argument[0] == :colon2
|
1375
|
+
argument[1]
|
1085
1376
|
end
|
1377
|
+
end
|
1378
|
+
end
|
1086
1379
|
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
value_cast = value_cast + ", VALUE,VALUE" if convention == :fastruby
|
1380
|
+
def locals_scope(locals)
|
1381
|
+
old_locals = @locals
|
1382
|
+
old_locals_struct = @locals_struct
|
1091
1383
|
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1384
|
+
@locals = locals
|
1385
|
+
@locals_struct = "struct {
|
1386
|
+
void* block_function_address;
|
1387
|
+
VALUE block_function_param;
|
1388
|
+
jmp_buf jmp;
|
1389
|
+
VALUE return_value;
|
1390
|
+
void* pframe;
|
1391
|
+
#{@locals.map{|l| "VALUE #{l};\n"}.join}
|
1392
|
+
}"
|
1095
1393
|
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
else
|
1104
|
-
str_incall_args = "recv"
|
1105
|
-
end
|
1394
|
+
begin
|
1395
|
+
yield
|
1396
|
+
ensure
|
1397
|
+
@locals = old_locals
|
1398
|
+
@locals_struct = old_locals_struct
|
1399
|
+
end
|
1400
|
+
end
|
1106
1401
|
|
1107
|
-
|
1108
|
-
|
1109
|
-
anonymous_function{ |name| "
|
1110
|
-
static VALUE #{name}(VALUE recv#{extraargs_signature}) {
|
1111
|
-
// call to #{recvtype}##{mname}
|
1112
|
-
if (rb_block_given_p()) {
|
1113
|
-
// no passing block, recall
|
1114
|
-
return rb_funcall(recv, #{tree[2].to_i}, 0);
|
1115
|
-
} else {
|
1116
|
-
return ((VALUE(*)(#{value_cast}))0x#{address.to_s(16)})(#{str_incall_args});
|
1117
|
-
}
|
1118
|
-
}
|
1119
|
-
" } + "(#{to_c(recv)}#{extraargs})", false, repass_var)
|
1120
|
-
end
|
1121
|
-
else
|
1122
|
-
value_cast = ( ["VALUE"]*(args.size) ).join(",")
|
1123
|
-
value_cast = value_cast + ", VALUE, VALUE" if convention == :fastruby
|
1402
|
+
def method_group(init_code, tree)
|
1124
1403
|
|
1125
|
-
|
1126
|
-
|
1127
|
-
"((VALUE(*)(#{value_cast}))0x#{address.to_s(16)})(#{to_c recv}, Qfalse, (VALUE)pframe, #{strargs})"
|
1128
|
-
else
|
1404
|
+
alt_locals = Set.new
|
1405
|
+
alt_locals << :self
|
1129
1406
|
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1133
|
-
value_cast = "int,VALUE*,VALUE"
|
1134
|
-
elsif len == -2
|
1135
|
-
str_incall_args = "recv, rb_ary_new4(#{ (1..argnum).map{|x| "_arg"+x.to_s }.join(",")})"
|
1136
|
-
value_cast = "VALUE,VALUE"
|
1137
|
-
else
|
1138
|
-
str_incall_args = "recv, #{ (1..argnum).map{|x| "_arg"+x.to_s }.join(",")}"
|
1139
|
-
end
|
1407
|
+
FastRuby::GetLocalsProcessor.get_locals(tree).each do |local|
|
1408
|
+
alt_locals << local
|
1409
|
+
end
|
1140
1410
|
|
1141
|
-
|
1142
|
-
|
1143
|
-
anonymous_function{ |name| "
|
1144
|
-
static VALUE #{name}(VALUE recv, #{ (1..argnum).map{|x| "VALUE _arg"+x.to_s }.join(",")} ) {
|
1145
|
-
// call to #{recvtype}##{mname}
|
1146
|
-
if (rb_block_given_p()) {
|
1147
|
-
// no passing block, recall
|
1148
|
-
return rb_funcall(recv, #{tree[2].to_i}, #{argnum}, #{ (1..argnum).map{|x| "_arg"+x.to_s }.join(",")});
|
1149
|
-
} else {
|
1150
|
-
return ((VALUE(*)(#{value_cast}))0x#{address.to_s(16)})(#{str_incall_args});
|
1151
|
-
}
|
1152
|
-
}
|
1153
|
-
" } + "(#{to_c(recv)}, #{strargs})", false, repass_var
|
1154
|
-
)
|
1155
|
-
end
|
1156
|
-
end
|
1157
|
-
else
|
1411
|
+
fun = nil
|
1158
1412
|
|
1159
|
-
|
1160
|
-
|
1161
|
-
else
|
1162
|
-
protected_block("rb_funcall(#{to_c recv}, #{tree[2].to_i}, #{argnum}, #{strargs} )", false, repass_var)
|
1163
|
-
end
|
1164
|
-
end
|
1413
|
+
locals_scope(alt_locals) do
|
1414
|
+
fun = anonymous_function { |method_name| "static VALUE #{method_name}(VALUE self) {
|
1165
1415
|
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1416
|
+
#{@frame_struct} frame;
|
1417
|
+
#{@locals_struct} locals;
|
1418
|
+
typeof(&frame) pframe = &frame;
|
1419
|
+
typeof(&locals) plocals = &locals;
|
1420
|
+
|
1421
|
+
frame.plocals = plocals;
|
1422
|
+
frame.parent_frame = 0;
|
1423
|
+
frame.return_value = Qnil;
|
1424
|
+
frame.target_frame = &frame;
|
1425
|
+
frame.exception = Qnil;
|
1426
|
+
frame.rescue = 0;
|
1427
|
+
|
1428
|
+
locals.self = self;
|
1429
|
+
|
1430
|
+
#{to_c tree};
|
1431
|
+
return Qnil;
|
1432
|
+
}
|
1433
|
+
"
|
1434
|
+
}
|
1172
1435
|
end
|
1173
|
-
end
|
1174
1436
|
|
1175
|
-
def to_c_class(tree)
|
1176
1437
|
inline_block("
|
1177
|
-
|
1438
|
+
#{init_code}
|
1439
|
+
|
1440
|
+
rb_funcall(tmpklass, #{intern_num :__id__},0);
|
1441
|
+
|
1442
|
+
#{fun}(tmpklass);
|
1178
1443
|
return Qnil;
|
1444
|
+
|
1445
|
+
|
1179
1446
|
")
|
1180
1447
|
|
1181
1448
|
end
|
1182
1449
|
|
1450
|
+
|
1451
|
+
|
1452
|
+
def to_c_class(tree)
|
1453
|
+
str_class_name = get_class_name(tree[1])
|
1454
|
+
container_tree = get_container_tree(tree[1])
|
1455
|
+
|
1456
|
+
if container_tree == s(:self)
|
1457
|
+
method_group("
|
1458
|
+
VALUE tmpklass = rb_define_class(
|
1459
|
+
#{str_class_name.inspect},
|
1460
|
+
#{tree[2] ? to_c(tree[2]) : "rb_cObject"}
|
1461
|
+
);
|
1462
|
+
", tree[3])
|
1463
|
+
else
|
1464
|
+
method_group("
|
1465
|
+
VALUE container_klass = #{to_c(container_tree)};
|
1466
|
+
VALUE tmpklass = rb_define_class_under(
|
1467
|
+
container_klass,
|
1468
|
+
#{str_class_name.inspect},
|
1469
|
+
#{tree[2] ? to_c(tree[2]) : "rb_cObject"}
|
1470
|
+
);
|
1471
|
+
", tree[3])
|
1472
|
+
end
|
1473
|
+
end
|
1474
|
+
|
1183
1475
|
def to_c_module(tree)
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1476
|
+
str_class_name = get_class_name(tree[1])
|
1477
|
+
container_tree = get_container_tree(tree[1])
|
1478
|
+
|
1479
|
+
if container_tree == s(:self)
|
1480
|
+
method_group("
|
1481
|
+
VALUE tmpklass = rb_define_module(#{str_class_name.inspect});
|
1482
|
+
", tree[2])
|
1483
|
+
else
|
1484
|
+
method_group("
|
1485
|
+
VALUE container_klass = #{to_c(container_tree)};
|
1486
|
+
VALUE tmpklass = rb_define_module_under(container_klass,#{str_class_name.inspect});
|
1487
|
+
", tree[2])
|
1488
|
+
end
|
1188
1489
|
end
|
1189
1490
|
|
1190
1491
|
def to_c_while(tree)
|
@@ -1271,7 +1572,7 @@ module FastRuby
|
|
1271
1572
|
def inline_block_reference(arg)
|
1272
1573
|
code = nil
|
1273
1574
|
|
1274
|
-
if arg.instance_of?
|
1575
|
+
if arg.instance_of? FastRuby::FastRubySexp
|
1275
1576
|
code = to_c(arg);
|
1276
1577
|
else
|
1277
1578
|
code = arg
|
@@ -1292,7 +1593,7 @@ module FastRuby
|
|
1292
1593
|
|
1293
1594
|
def inline_block(code, repass_var = nil)
|
1294
1595
|
anonymous_function{ |name| "
|
1295
|
-
static VALUE #{name}(VALUE param#{repass_var ? ",
|
1596
|
+
static VALUE #{name}(VALUE param#{repass_var ? ",void* " + repass_var : "" }) {
|
1296
1597
|
#{@frame_struct} *pframe = (void*)param;
|
1297
1598
|
#{@locals_struct} *plocals = (void*)pframe->plocals;
|
1298
1599
|
VALUE last_expression = Qnil;
|
@@ -1304,7 +1605,7 @@ module FastRuby
|
|
1304
1605
|
end
|
1305
1606
|
|
1306
1607
|
def inline_ruby(proced, parameter)
|
1307
|
-
"rb_funcall(#{proced.
|
1608
|
+
"rb_funcall(#{proced.__id__}, #{intern_num :call}, 1, #{parameter})"
|
1308
1609
|
end
|
1309
1610
|
|
1310
1611
|
def wrapped_break_block(inner_code)
|
@@ -1318,12 +1619,12 @@ module FastRuby
|
|
1318
1619
|
def protected_block(inner_code, always_rescue = false,repass_var = nil)
|
1319
1620
|
wrapper_code = "
|
1320
1621
|
if (pframe->last_error != Qnil) {
|
1321
|
-
if (CLASS_OF(pframe->last_error)
|
1622
|
+
if (CLASS_OF(pframe->last_error)==#{literal_value FastRuby::Context::UnwindFastrubyFrame}) {
|
1322
1623
|
#{@frame_struct} *pframe = (void*)param;
|
1323
1624
|
|
1324
|
-
pframe->target_frame = (void*)FIX2LONG(rb_ivar_get(pframe->last_error, #{:@target_frame
|
1325
|
-
pframe->exception = rb_ivar_get(pframe->last_error, #{:@ex
|
1326
|
-
pframe->return_value = rb_ivar_get(pframe->last_error, #{:@return_value
|
1625
|
+
pframe->target_frame = (void*)FIX2LONG(rb_ivar_get(pframe->last_error, #{intern_num :@target_frame}));
|
1626
|
+
pframe->exception = rb_ivar_get(pframe->last_error, #{intern_num :@ex});
|
1627
|
+
pframe->return_value = rb_ivar_get(pframe->last_error, #{intern_num :@return_value});
|
1327
1628
|
|
1328
1629
|
if (pframe->target_frame == (void*)-2) {
|
1329
1630
|
return pframe->return_value;
|
@@ -1360,7 +1661,7 @@ module FastRuby
|
|
1360
1661
|
}
|
1361
1662
|
|
1362
1663
|
rescue_args = ""
|
1363
|
-
rescue_args = "(VALUE)(VALUE[]){(VALUE)pframe
|
1664
|
+
rescue_args = "(VALUE)(VALUE[]){(VALUE)pframe,(VALUE)#{repass_var}}"
|
1364
1665
|
else
|
1365
1666
|
body = inline_block_reference("return #{inner_code}")
|
1366
1667
|
rescue_args = "(VALUE)pframe"
|
@@ -1446,6 +1747,216 @@ module FastRuby
|
|
1446
1747
|
"
|
1447
1748
|
end
|
1448
1749
|
|
1750
|
+
def c_escape(str)
|
1751
|
+
str.inspect
|
1752
|
+
end
|
1753
|
+
|
1754
|
+
def literal_value(value)
|
1755
|
+
@literal_value_hash = Hash.new unless @literal_value_hash
|
1756
|
+
return @literal_value_hash[value] if @literal_value_hash[value]
|
1757
|
+
|
1758
|
+
name = self.add_global_name("VALUE", "Qnil");
|
1759
|
+
|
1760
|
+
begin
|
1761
|
+
str = Marshal.dump(value)
|
1762
|
+
|
1763
|
+
init_extra << "
|
1764
|
+
#{name} = rb_marshal_load(rb_str_new(#{c_escape str}, #{str.size}));
|
1765
|
+
rb_funcall(#{name},#{intern_num :gc_register_object},0);
|
1766
|
+
|
1767
|
+
"
|
1768
|
+
rescue TypeError
|
1769
|
+
@no_cache = true
|
1770
|
+
FastRuby.logger.info "#{value} disabling cache for extension"
|
1771
|
+
init_extra << "
|
1772
|
+
#{name} = rb_funcall(rb_const_get(rb_cObject, #{intern_num :ObjectSpace}), #{intern_num :_id2ref}, 1, INT2FIX(#{value.__id__}));
|
1773
|
+
"
|
1774
|
+
|
1775
|
+
end
|
1776
|
+
@literal_value_hash[value] = name
|
1777
|
+
|
1778
|
+
name
|
1779
|
+
end
|
1780
|
+
|
1781
|
+
def encode_address(recvtype,signature,mname,call_tree,inference_complete,convention_global_name = nil)
|
1782
|
+
name = self.add_global_name("void*", 0);
|
1783
|
+
cruby_name = self.add_global_name("void*", 0);
|
1784
|
+
cruby_len = self.add_global_name("int", 0);
|
1785
|
+
args_tree = call_tree[3]
|
1786
|
+
method_tree = nil
|
1787
|
+
|
1788
|
+
begin
|
1789
|
+
method_tree = recvtype.instance_method(@method_name.to_sym).fastruby.tree
|
1790
|
+
rescue NoMethodError
|
1791
|
+
end
|
1792
|
+
|
1793
|
+
|
1794
|
+
strargs_signature = (0..args_tree.size-2).map{|x| "VALUE arg#{x}"}.join(",")
|
1795
|
+
strargs = (0..args_tree.size-2).map{|x| "arg#{x}"}.join(",")
|
1796
|
+
inprocstrargs = (1..args_tree.size-1).map{|x| "((VALUE*)method_arguments)[#{x}]"}.join(",")
|
1797
|
+
|
1798
|
+
if args_tree.size > 1
|
1799
|
+
strargs_signature = "," + strargs_signature
|
1800
|
+
toprocstrargs = "self,"+strargs
|
1801
|
+
strargs = "," + strargs
|
1802
|
+
inprocstrargs = ","+inprocstrargs
|
1803
|
+
else
|
1804
|
+
toprocstrargs = "self"
|
1805
|
+
end
|
1806
|
+
|
1807
|
+
ruby_wrapper = anonymous_function{ |funcname| "
|
1808
|
+
static VALUE #{funcname}(VALUE self,void* block,void* frame#{strargs_signature}){
|
1809
|
+
#{@frame_struct}* pframe = frame;
|
1810
|
+
|
1811
|
+
VALUE method_arguments[#{args_tree.size}] = {#{toprocstrargs}};
|
1812
|
+
|
1813
|
+
return #{
|
1814
|
+
protected_block "rb_funcall(((VALUE*)method_arguments)[0], #{intern_num mname.to_sym}, #{args_tree.size-1}#{inprocstrargs});", false, "method_arguments"
|
1815
|
+
};
|
1816
|
+
}
|
1817
|
+
"
|
1818
|
+
}
|
1819
|
+
|
1820
|
+
value_cast = ( ["VALUE"]*(args_tree.size) ).join(",")
|
1821
|
+
|
1822
|
+
cruby_wrapper = anonymous_function{ |funcname| "
|
1823
|
+
static VALUE #{funcname}(VALUE self,void* block,void* frame#{strargs_signature}){
|
1824
|
+
#{@frame_struct}* pframe = frame;
|
1825
|
+
|
1826
|
+
VALUE method_arguments[#{args_tree.size}] = {#{toprocstrargs}};
|
1827
|
+
|
1828
|
+
// call to #{recvtype}::#{mname}
|
1829
|
+
|
1830
|
+
if (#{cruby_len} == -1) {
|
1831
|
+
return #{
|
1832
|
+
protected_block "((VALUE(*)(int,VALUE*,VALUE))#{cruby_name})(#{args_tree.size-1}, ((VALUE*)method_arguments)+1,*((VALUE*)method_arguments));", false, "method_arguments"
|
1833
|
+
};
|
1834
|
+
|
1835
|
+
} else if (#{cruby_len} == -2) {
|
1836
|
+
return #{
|
1837
|
+
protected_block "((VALUE(*)(VALUE,VALUE))#{cruby_name})(*((VALUE*)method_arguments), rb_ary_new4(#{args_tree.size-1},((VALUE*)method_arguments)+1) );", false, "method_arguments"
|
1838
|
+
};
|
1839
|
+
|
1840
|
+
} else {
|
1841
|
+
return #{
|
1842
|
+
protected_block "((VALUE(*)(#{value_cast}))#{cruby_name})(((VALUE*)method_arguments)[0] #{inprocstrargs});", false, "method_arguments"
|
1843
|
+
};
|
1844
|
+
}
|
1845
|
+
}
|
1846
|
+
"
|
1847
|
+
}
|
1848
|
+
|
1849
|
+
recvdump = nil
|
1850
|
+
|
1851
|
+
begin
|
1852
|
+
recvdump = literal_value recvtype
|
1853
|
+
rescue
|
1854
|
+
end
|
1855
|
+
|
1856
|
+
if recvdump and recvtype
|
1857
|
+
init_extra << "
|
1858
|
+
{
|
1859
|
+
VALUE recvtype = #{recvdump};
|
1860
|
+
rb_funcall(#{literal_value FastRuby}, #{intern_num :set_builder_module}, 1, recvtype);
|
1861
|
+
VALUE signature = #{literal_value signature};
|
1862
|
+
VALUE mname = #{literal_value mname};
|
1863
|
+
VALUE tree = #{literal_value method_tree};
|
1864
|
+
VALUE convention = rb_funcall(recvtype, #{intern_num :convention}, 3,signature,mname,#{inference_complete ? "Qtrue" : "Qfalse"});
|
1865
|
+
VALUE mobject = rb_funcall(recvtype, #{intern_num :method_from_signature},3,signature,mname,#{inference_complete ? "Qtrue" : "Qfalse"});
|
1866
|
+
|
1867
|
+
struct METHOD {
|
1868
|
+
VALUE klass, rklass;
|
1869
|
+
VALUE recv;
|
1870
|
+
ID id, oid;
|
1871
|
+
int safe_level;
|
1872
|
+
NODE *body;
|
1873
|
+
};
|
1874
|
+
|
1875
|
+
int len = 0;
|
1876
|
+
void* address = 0;
|
1877
|
+
|
1878
|
+
if (mobject != Qnil) {
|
1879
|
+
|
1880
|
+
struct METHOD *data;
|
1881
|
+
Data_Get_Struct(mobject, struct METHOD, data);
|
1882
|
+
|
1883
|
+
if (nd_type(data->body) == NODE_CFUNC) {
|
1884
|
+
address = data->body->nd_cfnc;
|
1885
|
+
len = data->body->nd_argc;
|
1886
|
+
}
|
1887
|
+
}
|
1888
|
+
|
1889
|
+
#{convention_global_name ? convention_global_name + " = 0;" : ""}
|
1890
|
+
if (recvtype != Qnil) {
|
1891
|
+
|
1892
|
+
if (convention == #{literal_value :fastruby}) {
|
1893
|
+
#{convention_global_name ? convention_global_name + " = 1;" : ""}
|
1894
|
+
#{name} = address;
|
1895
|
+
} else if (convention == #{literal_value :cruby}) {
|
1896
|
+
// cruby, wrap direct call
|
1897
|
+
#{cruby_name} = address;
|
1898
|
+
|
1899
|
+
if (#{cruby_name} == 0) {
|
1900
|
+
#{name} = (void*)#{ruby_wrapper};
|
1901
|
+
} else {
|
1902
|
+
#{cruby_len} = len;
|
1903
|
+
#{name} = (void*)#{cruby_wrapper};
|
1904
|
+
}
|
1905
|
+
} else {
|
1906
|
+
// ruby, wrap rb_funcall
|
1907
|
+
#{name} = (void*)#{ruby_wrapper};
|
1908
|
+
}
|
1909
|
+
} else {
|
1910
|
+
// ruby, wrap rb_funcall
|
1911
|
+
#{name} = (void*)#{ruby_wrapper};
|
1912
|
+
}
|
1913
|
+
|
1914
|
+
}
|
1915
|
+
"
|
1916
|
+
else
|
1917
|
+
init_extra << "
|
1918
|
+
// ruby, wrap rb_funcall
|
1919
|
+
#{name} = (void*)#{ruby_wrapper};
|
1920
|
+
"
|
1921
|
+
end
|
1922
|
+
|
1923
|
+
name
|
1924
|
+
end
|
1925
|
+
|
1926
|
+
def intern_num(symbol)
|
1927
|
+
@intern_num_hash = Hash.new unless @intern_num_hash
|
1928
|
+
return @intern_num_hash[symbol] if @intern_num_hash[symbol]
|
1929
|
+
|
1930
|
+
name = self.add_global_name("ID", 0);
|
1931
|
+
|
1932
|
+
init_extra << "
|
1933
|
+
#{name} = rb_intern(\"#{symbol.to_s}\");
|
1934
|
+
"
|
1935
|
+
|
1936
|
+
@intern_num_hash[symbol] = name
|
1937
|
+
|
1938
|
+
name
|
1939
|
+
end
|
1940
|
+
|
1941
|
+
def add_global_name(ctype, default)
|
1942
|
+
name = "glb" + rand(1000000000).to_s
|
1943
|
+
|
1944
|
+
extra_code << "
|
1945
|
+
static #{ctype} #{name} = #{default};
|
1946
|
+
"
|
1947
|
+
name
|
1948
|
+
end
|
1949
|
+
|
1950
|
+
def global_entry(glbname)
|
1951
|
+
name = add_global_name("struct global_entry*", 0);
|
1952
|
+
|
1953
|
+
init_extra << "
|
1954
|
+
#{name} = rb_global_entry(SYM2ID(#{literal_value glbname}));
|
1955
|
+
"
|
1956
|
+
|
1957
|
+
name
|
1958
|
+
end
|
1959
|
+
|
1449
1960
|
|
1450
1961
|
def frame(code, jmp_code, not_jmp_code = "", rescued = nil)
|
1451
1962
|
|
@@ -1498,55 +2009,5 @@ module FastRuby
|
|
1498
2009
|
"
|
1499
2010
|
} + "((VALUE)pframe)"
|
1500
2011
|
end
|
1501
|
-
|
1502
|
-
inline :C do |builder|
|
1503
|
-
builder.include "<node.h>"
|
1504
|
-
builder.c "VALUE getaddress(VALUE method) {
|
1505
|
-
struct METHOD {
|
1506
|
-
VALUE klass, rklass;
|
1507
|
-
VALUE recv;
|
1508
|
-
ID id, oid;
|
1509
|
-
int safe_level;
|
1510
|
-
NODE *body;
|
1511
|
-
};
|
1512
|
-
|
1513
|
-
struct METHOD *data;
|
1514
|
-
Data_Get_Struct(method, struct METHOD, data);
|
1515
|
-
|
1516
|
-
if (nd_type(data->body) == NODE_CFUNC) {
|
1517
|
-
return INT2FIX(data->body->nd_cfnc);
|
1518
|
-
}
|
1519
|
-
|
1520
|
-
return Qnil;
|
1521
|
-
}"
|
1522
|
-
|
1523
|
-
builder.c "VALUE getlen(VALUE method) {
|
1524
|
-
struct METHOD {
|
1525
|
-
VALUE klass, rklass;
|
1526
|
-
VALUE recv;
|
1527
|
-
ID id, oid;
|
1528
|
-
int safe_level;
|
1529
|
-
NODE *body;
|
1530
|
-
};
|
1531
|
-
|
1532
|
-
struct METHOD *data;
|
1533
|
-
Data_Get_Struct(method, struct METHOD, data);
|
1534
|
-
|
1535
|
-
if (nd_type(data->body) == NODE_CFUNC) {
|
1536
|
-
return INT2FIX(data->body->nd_argc);
|
1537
|
-
}
|
1538
|
-
|
1539
|
-
return Qnil;
|
1540
|
-
}"
|
1541
|
-
|
1542
|
-
builder.c "VALUE global_entry(VALUE global_id) {
|
1543
|
-
ID id = SYM2ID(global_id);
|
1544
|
-
struct global_entry* entry;
|
1545
|
-
|
1546
|
-
entry = rb_global_entry(id);
|
1547
|
-
return INT2FIX(entry);
|
1548
|
-
}
|
1549
|
-
"
|
1550
|
-
end
|
1551
2012
|
end
|
1552
2013
|
end
|