fastruby 0.0.21 → 0.0.22
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/Rakefile +1 -1
- data/benchmarks/benchmark.rb +3 -0
- data/benchmarks/benchmark.rb~ +3 -12
- data/benchmarks/benchmark8.rb +48 -0
- data/benchmarks/benchmark8.rb~ +46 -0
- data/lib/fastruby.rb +2 -1
- data/lib/fastruby.rb~ +2 -1
- data/lib/fastruby/builder.rb +18 -1
- data/lib/fastruby/builder.rb~ +18 -5
- data/lib/fastruby/modules/lvar_type/lasgn.rb~ +41 -0
- data/lib/fastruby/modules/translator/block.rb +1 -1
- data/lib/fastruby/modules/translator/block.rb~ +128 -0
- data/lib/fastruby/modules/translator/call.rb +62 -139
- data/lib/fastruby/modules/translator/call.rb~ +61 -140
- data/lib/fastruby/modules/translator/defn.rb +49 -105
- data/lib/fastruby/modules/translator/defn.rb~ +211 -0
- data/lib/fastruby/modules/translator/exceptions.rb +1 -0
- data/lib/fastruby/modules/translator/exceptions.rb~ +120 -0
- data/lib/fastruby/modules/translator/iter.rb +13 -20
- data/lib/fastruby/modules/translator/iter.rb~ +738 -0
- data/lib/fastruby/modules/translator/literal.rb +8 -1
- data/lib/fastruby/modules/translator/literal.rb~ +157 -0
- data/lib/fastruby/modules/translator/nonlocal.rb +7 -0
- data/lib/fastruby/modules/translator/nonlocal.rb~ +304 -0
- data/lib/fastruby/modules/translator/static.rb +1 -0
- data/lib/fastruby/modules/translator/static.rb~ +290 -0
- data/lib/fastruby/modules/translator/variable.rb +24 -6
- data/lib/fastruby/modules/translator/variable.rb~ +298 -0
- data/lib/fastruby/translator/translator.rb +411 -284
- data/lib/fastruby/translator/translator.rb~ +1728 -0
- data/spec/fastruby_only/base_spec.rb~ +74 -0
- data/spec/ruby/base_spec.rb~ +1 -338
- data/spec/ruby/block/break_spec.rb~ +21 -0
- data/spec/ruby/block/callcc_spec.rb~ +236 -0
- data/spec/ruby/block/lambda_spec.rb~ +1 -178
- data/spec/ruby/block/next_spec.rb~ +85 -0
- data/spec/ruby/block/proc_spec.rb~ +22 -0
- data/spec/ruby/block/redo_spec.rb~ +133 -0
- data/spec/ruby/block/retry_spec.rb~ +135 -0
- data/spec/ruby/block_spec.rb~ +494 -2
- data/spec/ruby/call/base_call_spec.rb~ +60 -2
- data/spec/ruby/defn/default_args_spec.rb~ +303 -0
- data/spec/ruby/defn/multiple_args_spec.rb~ +317 -0
- data/spec/ruby/defn/replacement_spec.rb +29 -1
- data/spec/ruby/defn/replacement_spec.rb~ +52 -21
- data/spec/ruby/exception/internal_ex_spec.rb~ +2 -2
- data/spec/ruby/variable_spec.rb~ +46 -23
- data/spec/static/flow_spec.rb~ +48 -0
- metadata +34 -12
@@ -250,6 +250,8 @@ module FastRuby
|
|
250
250
|
|
251
251
|
|
252
252
|
def _raise(class_tree, message_tree = nil)
|
253
|
+
@has_raise = true
|
254
|
+
@has_inline_block = true
|
253
255
|
class_tree = to_c class_tree unless class_tree.instance_of? String
|
254
256
|
|
255
257
|
if message_tree.instance_of? String
|
@@ -443,6 +445,8 @@ module FastRuby
|
|
443
445
|
block_argument = tree[3].find{|x| x.to_s[0] == ?&}
|
444
446
|
impl_tree = tree[4][1]
|
445
447
|
end
|
448
|
+
|
449
|
+
@method_arguments = original_args_tree[1..-1]
|
446
450
|
|
447
451
|
if "0".respond_to?(:ord)
|
448
452
|
@alt_method_name = "_" + method_name.to_s.gsub("_x_", "_x__x_").gsub(/\W/){|x| "_x_#{x.ord}" } + "_" + rand(10000000000).to_s
|
@@ -450,6 +454,14 @@ module FastRuby
|
|
450
454
|
@alt_method_name = "_" + method_name.to_s.gsub("_x_", "_x__x_").gsub(/\W/){|x| "_x_#{x[0]}" } + "_" + rand(10000000000).to_s
|
451
455
|
end
|
452
456
|
|
457
|
+
@has_yield = false
|
458
|
+
@has_dynamic_call = false
|
459
|
+
@has_nonlocal_goto = false
|
460
|
+
@has_inline_block = (options[:main] or tree.find_tree(:lasgn))
|
461
|
+
@has_plocals_ref = false
|
462
|
+
@has_raise = false
|
463
|
+
@has_inline_c = false
|
464
|
+
|
453
465
|
args_tree = original_args_tree.select{|x| x.to_s[0] != ?&}
|
454
466
|
|
455
467
|
initialize_method_structs(original_args_tree)
|
@@ -534,6 +546,7 @@ module FastRuby
|
|
534
546
|
else
|
535
547
|
|
536
548
|
if default_block_tree
|
549
|
+
@has_inline_block = true
|
537
550
|
initialize_tree = default_block_tree[1..-1].find{|subtree| subtree[1] == arg_}
|
538
551
|
if initialize_tree
|
539
552
|
to_c(initialize_tree) + ";\n"
|
@@ -550,6 +563,7 @@ module FastRuby
|
|
550
563
|
}.join("")
|
551
564
|
|
552
565
|
if splat_arg
|
566
|
+
@has_splat_args = true
|
553
567
|
if signature.size-1 < normalargsnum then
|
554
568
|
read_arguments_code << "
|
555
569
|
plocals->#{splat_arg.to_s.gsub("*","")} = rb_ary_new3(0);
|
@@ -569,6 +583,8 @@ module FastRuby
|
|
569
583
|
end
|
570
584
|
|
571
585
|
if block_argument
|
586
|
+
|
587
|
+
@has_yield = true
|
572
588
|
|
573
589
|
proc_reyield_block_tree = s(:iter, s(:call, nil, :proc, s(:arglist)), s(:masgn, s(:array, s(:splat, s(:lasgn, :__xproc_arguments)))), s(:yield, s(:splat, s(:lvar, :__xproc_arguments))))
|
574
590
|
|
@@ -615,11 +631,29 @@ module FastRuby
|
|
615
631
|
}
|
616
632
|
|
617
633
|
evaluate_tree = tree.transform &trs
|
634
|
+
|
635
|
+
impl_code = to_c(impl_tree, "last_expression")
|
636
|
+
|
637
|
+
put_setjmp = (@has_dynamic_call or @has_nonlocal_goto or @has_yield or @has_raise or @has_inline_c)
|
638
|
+
put_block_init = @has_yield
|
639
|
+
if options[:main]
|
640
|
+
put_block_init = false
|
641
|
+
end
|
618
642
|
|
619
643
|
scope_mode = FastRuby::ScopeModeHelper.get_scope_mode(evaluate_tree)
|
644
|
+
if scope_mode == :dag or put_setjmp or put_block_init or @has_splat_args
|
645
|
+
put_frame = true
|
646
|
+
put_locals = true
|
647
|
+
else
|
648
|
+
put_frame = @has_inline_block
|
649
|
+
put_locals = @has_plocals_ref
|
650
|
+
end
|
651
|
+
|
620
652
|
ret = "VALUE #{@alt_method_name || method_name}(#{options[:main] ? "VALUE self" : strargs}) {
|
621
653
|
#{validate_arguments_code}
|
622
654
|
|
655
|
+
#{if put_frame
|
656
|
+
"
|
623
657
|
#{@frame_struct} frame;
|
624
658
|
#{@frame_struct} * volatile pframe;
|
625
659
|
|
@@ -629,12 +663,15 @@ module FastRuby
|
|
629
663
|
frame.targetted = 0;
|
630
664
|
frame.thread_data = #{options[:main] ? "0" : "((typeof(pframe))_parent_frame)->thread_data"};
|
631
665
|
if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
|
632
|
-
|
633
|
-
|
666
|
+
"
|
667
|
+
end
|
668
|
+
}
|
634
669
|
|
635
670
|
#{
|
636
671
|
if scope_mode == :dag
|
637
672
|
"
|
673
|
+
int stack_chunk_instantiated = 0;
|
674
|
+
|
638
675
|
volatile VALUE rb_previous_stack_chunk = Qnil;
|
639
676
|
VALUE rb_stack_chunk = frame.thread_data->rb_stack_chunk;
|
640
677
|
struct STACKCHUNK* volatile stack_chunk = 0;
|
@@ -670,6 +707,8 @@ else
|
|
670
707
|
end
|
671
708
|
}
|
672
709
|
|
710
|
+
#{if put_locals and put_frame
|
711
|
+
"
|
673
712
|
plocals->parent_locals = (frame.thread_data->last_plocals);
|
674
713
|
void* volatile old_parent_locals = frame.thread_data->last_plocals;
|
675
714
|
|
@@ -680,16 +719,26 @@ end
|
|
680
719
|
}
|
681
720
|
|
682
721
|
frame.plocals = plocals;
|
722
|
+
plocals->pframe = (&frame);
|
723
|
+
pframe = (void*)&frame;
|
724
|
+
"
|
725
|
+
end
|
726
|
+
}
|
727
|
+
|
728
|
+
#{if put_locals
|
729
|
+
"
|
683
730
|
plocals->active = Qtrue;
|
684
731
|
plocals->targetted = Qfalse;
|
685
|
-
plocals->pframe = (&frame);
|
686
732
|
plocals->call_frame = (0);
|
733
|
+
"
|
734
|
+
end
|
735
|
+
}
|
687
736
|
|
688
|
-
pframe = (void*)&frame;
|
689
|
-
|
690
|
-
#{@block_struct} * volatile pblock;
|
691
737
|
volatile VALUE last_expression = Qnil;
|
692
738
|
|
739
|
+
#{if put_setjmp
|
740
|
+
"
|
741
|
+
|
693
742
|
int aux = setjmp(pframe->jmp);
|
694
743
|
if (aux != 0) {
|
695
744
|
plocals->active = Qfalse;
|
@@ -722,12 +771,21 @@ end
|
|
722
771
|
|
723
772
|
return plocals->return_value;
|
724
773
|
}
|
774
|
+
"
|
775
|
+
end
|
776
|
+
}
|
725
777
|
|
778
|
+
#{if put_locals
|
779
|
+
"
|
726
780
|
plocals->self = self;
|
781
|
+
"
|
782
|
+
end
|
783
|
+
}
|
727
784
|
|
728
785
|
#{
|
729
|
-
|
786
|
+
if put_block_init
|
730
787
|
"
|
788
|
+
#{@block_struct} * volatile pblock;
|
731
789
|
pblock = (void*)block;
|
732
790
|
if (pblock) {
|
733
791
|
plocals->block_function_address = pblock->block_function_address;
|
@@ -740,9 +798,14 @@ end
|
|
740
798
|
end
|
741
799
|
}
|
742
800
|
|
801
|
+
#{if put_locals
|
802
|
+
"
|
743
803
|
#{read_arguments_code}
|
804
|
+
"
|
805
|
+
end
|
806
|
+
}
|
744
807
|
|
745
|
-
#{
|
808
|
+
#{impl_code};
|
746
809
|
|
747
810
|
local_return:
|
748
811
|
#{
|
@@ -757,10 +820,21 @@ if scope_mode == :dag
|
|
757
820
|
"
|
758
821
|
end
|
759
822
|
}
|
823
|
+
|
824
|
+
#{if put_locals
|
825
|
+
"
|
760
826
|
plocals->active = Qfalse;
|
827
|
+
"
|
828
|
+
end
|
829
|
+
}
|
761
830
|
|
831
|
+
#{if put_locals and put_frame
|
832
|
+
"
|
762
833
|
frame.thread_data->last_plocals = old_parent_locals;
|
763
|
-
|
834
|
+
"
|
835
|
+
end
|
836
|
+
}
|
837
|
+
|
764
838
|
return last_expression;
|
765
839
|
}"
|
766
840
|
|
@@ -775,6 +849,7 @@ end
|
|
775
849
|
end
|
776
850
|
|
777
851
|
def locals_accessor
|
852
|
+
@has_plocals_ref = true
|
778
853
|
"plocals->"
|
779
854
|
end
|
780
855
|
|
@@ -830,9 +905,10 @@ end
|
|
830
905
|
if mname == :infer
|
831
906
|
return to_c(recv)
|
832
907
|
elsif mname == :block_given?
|
908
|
+
@has_yield = true
|
833
909
|
return "plocals->block_function_address == 0 ? Qfalse : Qtrue"
|
834
910
|
elsif mname == :inline_c
|
835
|
-
|
911
|
+
@has_inline_c = true
|
836
912
|
code = args[1][1]
|
837
913
|
|
838
914
|
unless (args[2] == s(:false))
|
@@ -856,6 +932,8 @@ end
|
|
856
932
|
end
|
857
933
|
|
858
934
|
def inline_block_reference(arg, nolocals = false)
|
935
|
+
@has_inline_block = true
|
936
|
+
|
859
937
|
code = nil
|
860
938
|
|
861
939
|
if arg.instance_of? FastRuby::FastRubySexp
|
@@ -891,6 +969,7 @@ end
|
|
891
969
|
end
|
892
970
|
|
893
971
|
def inline_block(*args)
|
972
|
+
@has_inline_block = true
|
894
973
|
|
895
974
|
unless block_given?
|
896
975
|
code = args.first
|
@@ -1188,324 +1267,358 @@ fastruby_local_next:
|
|
1188
1267
|
|
1189
1268
|
name
|
1190
1269
|
end
|
1270
|
+
|
1271
|
+
def dynamic_block_call(signature, mname)
|
1272
|
+
dynamic_call(signature, mname, true)
|
1273
|
+
end
|
1191
1274
|
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
@
|
1196
|
-
|
1197
|
-
|
1198
|
-
tree_pointer_name = self.add_global_name("VALUE*", 0);
|
1199
|
-
|
1200
|
-
if call_tree[3].select{|st| st.respond_to?(:node_type) ? st[0] == :block_pass : false}
|
1201
|
-
is_block_call = true
|
1202
|
-
end
|
1203
|
-
|
1204
|
-
args_tree = call_tree[3].reject{|st| st.respond_to?(:node_type) ? st[0] == :block_pass : false}
|
1205
|
-
method_tree = nil
|
1275
|
+
# returns a anonymous function who made a dynamic call
|
1276
|
+
def dynamic_call(signature, mname, return_on_block_call = false, funcall_fallback = true, global_klass_variable = nil)
|
1277
|
+
# TODO: initialize the table
|
1278
|
+
@has_dynamic_call = true
|
1279
|
+
max_argument_size = 0
|
1280
|
+
recvtype = signature.first
|
1206
1281
|
|
1207
|
-
|
1208
|
-
|
1209
|
-
rescue NoMethodError
|
1282
|
+
unless recvtype
|
1283
|
+
max_argument_size = max_argument_size + 1
|
1210
1284
|
end
|
1211
1285
|
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1286
|
+
compare_hash = {}
|
1287
|
+
(1..signature.size-1).each do |j|
|
1288
|
+
unless signature[j]
|
1289
|
+
compare_hash[max_argument_size] = j-1
|
1290
|
+
max_argument_size = max_argument_size + 1
|
1291
|
+
end
|
1292
|
+
end
|
1215
1293
|
|
1216
|
-
if
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
inprocstrargs = ","+inprocstrargs
|
1294
|
+
table_size = if compare_hash.size == 0
|
1295
|
+
1
|
1296
|
+
elsif compare_hash.size == 1
|
1297
|
+
16
|
1221
1298
|
else
|
1222
|
-
|
1299
|
+
64
|
1223
1300
|
end
|
1224
1301
|
|
1225
|
-
|
1226
|
-
|
1227
|
-
recvdump = nil
|
1302
|
+
table_name = reserve_table(table_size, max_argument_size)
|
1228
1303
|
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
#{
|
1237
|
-
VALUE
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1304
|
+
if recvtype
|
1305
|
+
|
1306
|
+
init_extra << "{
|
1307
|
+
memset(#{table_name},0,sizeof(#{table_name}));
|
1308
|
+
|
1309
|
+
VALUE mname = #{literal_value mname};
|
1310
|
+
VALUE recvtype = #{literal_value recvtype};
|
1311
|
+
rb_funcall(#{literal_value FastRuby}, #{intern_num :set_builder_module}, 1, recvtype);
|
1312
|
+
VALUE fastruby_method = rb_funcall(recvtype, #{intern_num :fastruby_method}, 1, mname);
|
1313
|
+
rb_iterate(#{anonymous_function{|funcname|
|
1314
|
+
"static VALUE #{funcname}(VALUE recv) {
|
1315
|
+
return rb_funcall(recv, #{intern_num :observe}, 1, #{literal_value(mname.to_s + "#" + table_name.to_s)});
|
1316
|
+
}
|
1317
|
+
"
|
1318
|
+
}},fastruby_method,
|
1319
|
+
#{anonymous_function{|funcname|
|
1320
|
+
"static VALUE #{funcname}() {
|
1321
|
+
// clear table
|
1322
|
+
memset(#{table_name},0,sizeof(#{table_name}));
|
1323
|
+
return Qnil;
|
1324
|
+
}
|
1325
|
+
"
|
1326
|
+
}
|
1327
|
+
}
|
1328
|
+
,Qnil);
|
1246
1329
|
}
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
generic_wrapper = anonymous_function{ |funcname| "
|
1251
|
-
static VALUE #{funcname}(VALUE self,void* block,void* frame, int argc, VALUE* argv){
|
1330
|
+
"
|
1331
|
+
else
|
1252
1332
|
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1265
|
-
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
rb_funcall(recvtype, #{intern_num :build}, 2, signature, mname);
|
1333
|
+
# TODO: implemente this in ruby
|
1334
|
+
init_extra << "
|
1335
|
+
{
|
1336
|
+
memset(#{table_name},0,sizeof(#{table_name}));
|
1337
|
+
|
1338
|
+
rb_iterate(#{anonymous_function{|funcname|
|
1339
|
+
"static VALUE #{funcname}(VALUE recv) {
|
1340
|
+
return rb_funcall(recv, #{intern_num :observe_method_name}, 1, #{literal_value(mname.to_sym)});
|
1341
|
+
}
|
1342
|
+
"
|
1343
|
+
}},#{literal_value FastRuby::Method},
|
1344
|
+
#{anonymous_function{|funcname|
|
1345
|
+
"static VALUE #{funcname}() {
|
1346
|
+
// clear table
|
1347
|
+
memset(#{table_name},0,sizeof(#{table_name}));
|
1348
|
+
return Qnil;
|
1271
1349
|
}
|
1350
|
+
"
|
1272
1351
|
}
|
1273
|
-
|
1352
|
+
}
|
1353
|
+
,Qnil);
|
1274
1354
|
|
1275
|
-
|
1355
|
+
}
|
1356
|
+
"
|
1276
1357
|
|
1277
|
-
|
1278
|
-
fptr = *#{cfunc_address_name};
|
1279
|
-
if (fptr != 0) {
|
1280
|
-
return ( (VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*) ) (fptr) )(self,(VALUE)block,(VALUE)frame, argc, argv);
|
1281
|
-
}
|
1282
|
-
}
|
1358
|
+
end
|
1283
1359
|
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1360
|
+
anonymous_function{|funcname| "
|
1361
|
+
static VALUE #{funcname}(VALUE self,void* block,void* frame, int argc, VALUE* argv #{return_on_block_call ? ", int* block_call" : ""}){
|
1362
|
+
void* fptr = 0;
|
1363
|
+
#{if global_klass_variable
|
1364
|
+
"
|
1365
|
+
VALUE klass = #{global_klass_variable};
|
1366
|
+
"
|
1367
|
+
else
|
1368
|
+
"
|
1369
|
+
VALUE klass = CLASS_OF(self);
|
1370
|
+
"
|
1371
|
+
end
|
1372
|
+
}
|
1289
1373
|
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1296
|
-
|
1297
|
-
|
1298
|
-
|
1299
|
-
VALUE* method_arguments = (VALUE*)data;
|
1300
|
-
return rb_funcall2(((VALUE*)method_arguments)[2], #{intern_num mname.to_sym}, ((int*)method_arguments)[0], ((VALUE**)method_arguments)[1]);
|
1301
|
-
}
|
1302
|
-
"
|
1303
|
-
}},
|
1304
|
-
(VALUE)method_arguments,
|
1305
|
-
|
1306
|
-
#{anonymous_function{|name_|
|
1307
|
-
"
|
1308
|
-
static VALUE #{name_} (VALUE arg_, VALUE param, int argc, VALUE* argv) {
|
1309
|
-
|
1310
|
-
VALUE arg;
|
1311
|
-
#{
|
1312
|
-
# TODO: access directly to argc and argv for optimal execution
|
1313
|
-
if RUBY_VERSION =~ /^1\.9/
|
1314
|
-
"
|
1315
|
-
if (TYPE(arg_) == T_ARRAY) {
|
1316
|
-
if (_RARRAY_LEN(arg_) <= 1) {
|
1317
|
-
arg = rb_ary_new4(argc,argv);
|
1318
|
-
} else {
|
1319
|
-
arg = arg_;
|
1320
|
-
}
|
1321
|
-
} else {
|
1322
|
-
arg = rb_ary_new4(argc,argv);
|
1323
|
-
}
|
1374
|
+
char method_name[argc*40+64];
|
1375
|
+
|
1376
|
+
unsigned int fptr_hash = 0;
|
1377
|
+
int match = 1;
|
1378
|
+
|
1379
|
+
#{if table_size > 1
|
1380
|
+
"
|
1381
|
+
#{unless signature.first
|
1382
|
+
"fptr_hash = klass;
|
1324
1383
|
"
|
1325
|
-
else
|
1326
|
-
"arg = arg_;"
|
1327
1384
|
end
|
1328
1385
|
}
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1338
|
-
}
|
1386
|
+
|
1387
|
+
#{
|
1388
|
+
compare_hash.map { |k,v|
|
1389
|
+
"if (#{v} < argc) {
|
1390
|
+
fptr_hash += CLASS_OF(argv[#{v}]);
|
1391
|
+
}
|
1392
|
+
"
|
1393
|
+
}.join("\n")
|
1394
|
+
};
|
1339
1395
|
|
1340
|
-
|
1341
|
-
return ( (VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*)) (fptr) )(self,(VALUE)block,(VALUE)frame,argc,argv);
|
1342
|
-
}
|
1343
|
-
}
|
1344
|
-
"
|
1345
|
-
}
|
1396
|
+
fptr_hash = fptr_hash % #{table_size};
|
1346
1397
|
|
1398
|
+
int j = 0;
|
1347
1399
|
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
cfunc_wrapper = anonymous_function{ |funcname| "
|
1353
|
-
static VALUE #{funcname}(VALUE self, void* block,void* frame, int argc, VALUE* argv){
|
1354
|
-
return rb_vm_call(ruby_current_thread, self, #{intern_num mname.to_sym}, argc, argv, #{cfunc_real_address_name});
|
1355
|
-
}
|
1356
|
-
"
|
1357
|
-
}
|
1358
|
-
|
1359
|
-
toprocstrargs = (0..25).map{|x| "arg#{x}"}.join(",")
|
1360
|
-
strargs_signature = (0..25).map{|x| "VALUE arg#{x}"}.join(",")
|
1361
|
-
|
1362
|
-
cfunc_wrapper_1 = anonymous_function{ |funcname| "
|
1363
|
-
static VALUE #{funcname}(VALUE self, void* block,void* frame, int argc, VALUE* argv){
|
1364
|
-
return ( (VALUE(*)(int, VALUE*, VALUE)) (#{cfunc_real_address_name}) )(argc,argv,self);
|
1365
|
-
}
|
1366
|
-
"
|
1367
|
-
}
|
1368
|
-
|
1369
|
-
cfunc_wrapper_2 = anonymous_function{ |funcname| "
|
1370
|
-
static VALUE #{funcname}(VALUE self, void* block,void* frame, int argc, VALUE* argv){
|
1371
|
-
VALUE args = rb_ary_new3(argc, argv);
|
1372
|
-
return ( (VALUE(*)(VALUE,VALUE)) (#{cfunc_real_address_name}) )(self,args);
|
1373
|
-
}
|
1374
|
-
"
|
1375
|
-
}
|
1400
|
+
if (argc+15 != #{table_name}[fptr_hash].argc) {
|
1401
|
+
match = 0;
|
1402
|
+
goto does_not_match;
|
1403
|
+
}
|
1376
1404
|
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1381
|
-
|
1405
|
+
#{unless recvtype
|
1406
|
+
"
|
1407
|
+
if (match == 1 && #{table_name}[fptr_hash].argument_type[0] != klass ) {
|
1408
|
+
match = 0;
|
1409
|
+
goto does_not_match;
|
1410
|
+
}
|
1411
|
+
"
|
1412
|
+
end
|
1413
|
+
}
|
1382
1414
|
|
1383
|
-
|
1384
|
-
|
1385
|
-
|
1386
|
-
|
1387
|
-
|
1388
|
-
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1392
|
-
|
1393
|
-
|
1394
|
-
if (def->type == VM_METHOD_TYPE_CFUNC) {
|
1395
|
-
*default_address = #{cfunc_wrapper};
|
1396
|
-
#{cfunc_real_address_name} = (void*)me;
|
1397
|
-
}
|
1398
|
-
}
|
1399
|
-
"
|
1400
|
-
end
|
1401
|
-
}
|
1402
|
-
if (default_address != 0) {
|
1403
|
-
if (recvtype != Qnil) {
|
1404
|
-
rb_funcall(
|
1405
|
-
recvtype,
|
1406
|
-
#{intern_num :register_method_value},
|
1407
|
-
3,
|
1408
|
-
#{literal_value mname},
|
1409
|
-
PTR2NUM(default_id),
|
1410
|
-
PTR2NUM(default_address)
|
1411
|
-
);
|
1412
|
-
}
|
1413
|
-
}
|
1414
|
-
}
|
1415
|
-
return Qnil;
|
1415
|
+
#{
|
1416
|
+
compare_hash.map { |k,v|
|
1417
|
+
"if (match == 1 && #{table_name}[fptr_hash].argument_type[#{k}] != CLASS_OF(argv[#{v}])) {
|
1418
|
+
match = 0;
|
1419
|
+
goto does_not_match;
|
1420
|
+
}
|
1421
|
+
"
|
1422
|
+
}.join("\n")
|
1423
|
+
};
|
1424
|
+
"
|
1425
|
+
end
|
1416
1426
|
}
|
1417
|
-
"
|
1418
|
-
}
|
1419
|
-
|
1420
|
-
|
1421
1427
|
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1425
|
-
|
1426
|
-
|
1427
|
-
|
1428
|
-
|
1429
|
-
|
1430
|
-
|
1431
|
-
|
1432
|
-
#{intern_num :make_str_signature},
|
1433
|
-
2,
|
1434
|
-
mname,
|
1435
|
-
signature);
|
1436
|
-
|
1437
|
-
|
1438
|
-
|
1439
|
-
VALUE fastruby_method = rb_funcall(recvtype, #{intern_num :fastruby_method}, 1, mname);
|
1440
|
-
#{tree_pointer_name} = (VALUE*)NUM2PTR(fastruby_method_tree_pointer(fastruby_method));
|
1428
|
+
if (#{table_name}[fptr_hash].address == 0) match = 0;
|
1429
|
+
if (match == 1) {
|
1430
|
+
fptr = #{table_name}[fptr_hash].address;
|
1431
|
+
} else {
|
1432
|
+
does_not_match:
|
1433
|
+
method_name[0] = '_';
|
1434
|
+
method_name[1] = 0;
|
1435
|
+
|
1436
|
+
strncpy(method_name+1, \"#{mname}\",sizeof(method_name)-4);
|
1437
|
+
sprintf(method_name+strlen(method_name), \"%li\", (long)NUM2PTR(rb_obj_id(CLASS_OF(self))));
|
1441
1438
|
|
1439
|
+
int i;
|
1440
|
+
for (i=0; i<argc; i++) {
|
1441
|
+
sprintf(method_name+strlen(method_name), \"%li\", (long)NUM2PTR(rb_obj_id(CLASS_OF(argv[i]))));
|
1442
|
+
}
|
1443
|
+
|
1444
|
+
void** address = 0;
|
1442
1445
|
ID id;
|
1443
|
-
ID default_id = rb_intern(\"default\");
|
1444
1446
|
VALUE rb_method_hash;
|
1445
|
-
|
1446
|
-
|
1447
|
-
|
1448
|
-
|
1449
|
-
|
1450
|
-
|
1451
|
-
|
1452
|
-
|
1453
|
-
|
1447
|
+
|
1448
|
+
id = rb_intern(method_name);
|
1449
|
+
|
1450
|
+
if (rb_respond_to(klass, #{intern_num :method_hash})) {
|
1451
|
+
rb_method_hash = rb_funcall(klass, #{intern_num :method_hash},1,#{literal_value mname});
|
1452
|
+
|
1453
|
+
if (rb_method_hash != Qnil) {
|
1454
|
+
VALUE tmp = rb_hash_aref(rb_method_hash, PTR2NUM(id));
|
1455
|
+
if (tmp != Qnil) {
|
1456
|
+
address = (void**)NUM2PTR(tmp);
|
1457
|
+
fptr = *address;
|
1458
|
+
}
|
1454
1459
|
}
|
1455
1460
|
|
1456
|
-
|
1457
|
-
|
1458
|
-
|
1461
|
+
if (fptr == 0) {
|
1462
|
+
VALUE fastruby_method = rb_funcall(klass, #{intern_num :fastruby_method}, 1, #{literal_value mname});
|
1463
|
+
VALUE tree = rb_funcall(fastruby_method, #{intern_num :tree}, 0,0);
|
1464
|
+
|
1465
|
+
if (RTEST(tree)) {
|
1466
|
+
VALUE argv_class[argc+1];
|
1467
|
+
|
1468
|
+
argv_class[0] = CLASS_OF(self);
|
1469
|
+
for (i=0; i<argc; i++) {
|
1470
|
+
argv_class[i+1] = CLASS_OF(argv[i]);
|
1471
|
+
}
|
1472
|
+
|
1473
|
+
VALUE signature = rb_ary_new4(argc+1,argv_class);
|
1474
|
+
|
1475
|
+
rb_funcall(klass, #{intern_num :build}, 2, signature,rb_str_new2(#{mname.to_s.inspect}));
|
1476
|
+
|
1477
|
+
id = rb_intern(method_name);
|
1478
|
+
rb_method_hash = rb_funcall(klass, #{intern_num :method_hash},1,#{literal_value mname});
|
1479
|
+
|
1480
|
+
if (rb_method_hash != Qnil) {
|
1481
|
+
VALUE tmp = rb_hash_aref(rb_method_hash, PTR2NUM(id));
|
1482
|
+
if (tmp != Qnil) {
|
1483
|
+
address = (void**)NUM2PTR(tmp);
|
1484
|
+
fptr = *address;
|
1485
|
+
}
|
1486
|
+
}
|
1487
|
+
|
1488
|
+
if (fptr == 0) {
|
1489
|
+
rb_raise(rb_eRuntimeError, \"Error: method not found after build\");
|
1490
|
+
}
|
1491
|
+
}
|
1459
1492
|
}
|
1460
1493
|
}
|
1461
1494
|
|
1462
|
-
|
1463
|
-
|
1464
|
-
|
1465
|
-
|
1466
|
-
#{cfunc_address_name} = default_address;
|
1467
|
-
#{unless is_block_call
|
1495
|
+
// insert the value on table
|
1496
|
+
#{table_name}[fptr_hash].argc = argc+15;
|
1497
|
+
|
1498
|
+
#{unless recvtype
|
1468
1499
|
"
|
1469
|
-
#{
|
1470
|
-
rb_iterate(#{anonymous_function{|funcname|
|
1471
|
-
"static VALUE #{funcname}(VALUE recv) {
|
1472
|
-
return rb_funcall(recv, #{intern_num :observe}, 1, #{literal_value(@alt_method_name + "#" + cfunc_address_name)});
|
1473
|
-
}
|
1474
|
-
"
|
1475
|
-
}},fastruby_method,#{update_cfunc_method},Qnil);
|
1500
|
+
#{table_name}[fptr_hash].argument_type[0] = klass;
|
1476
1501
|
"
|
1477
1502
|
end
|
1478
1503
|
}
|
1479
1504
|
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
rb_funcall(
|
1485
|
-
recvtype,
|
1486
|
-
#{intern_num :register_method_value},
|
1487
|
-
3,
|
1488
|
-
#{literal_value mname},
|
1489
|
-
PTR2NUM(id),
|
1490
|
-
PTR2NUM(address)
|
1491
|
-
);
|
1505
|
+
#{
|
1506
|
+
compare_hash.map { |k,v|
|
1507
|
+
"if (#{v} < argc) {
|
1508
|
+
#{table_name}[fptr_hash].argument_type[#{k}] = CLASS_OF(argv[#{v}]);
|
1492
1509
|
}
|
1493
|
-
|
1494
|
-
|
1495
|
-
}
|
1510
|
+
"
|
1511
|
+
}.join("\n")
|
1512
|
+
};
|
1513
|
+
|
1514
|
+
#{table_name}[fptr_hash].address = fptr;
|
1515
|
+
}
|
1516
|
+
|
1517
|
+
if (fptr != 0) {
|
1518
|
+
return ((VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*))fptr)(self,(VALUE)block,(VALUE)frame, argc, argv);
|
1519
|
+
}
|
1520
|
+
|
1521
|
+
#{if funcall_fallback
|
1522
|
+
"
|
1523
|
+
|
1524
|
+
#{@frame_struct}* pframe = frame;
|
1525
|
+
VALUE method_arguments[4];
|
1526
|
+
|
1527
|
+
method_arguments[0] = (VALUE)argc;
|
1528
|
+
method_arguments[1] = (VALUE)argv;
|
1529
|
+
method_arguments[2] = (VALUE)self;
|
1530
|
+
method_arguments[3] = (VALUE)block;
|
1531
|
+
|
1532
|
+
if (block == 0) {
|
1533
|
+
return #{
|
1534
|
+
protected_block "
|
1535
|
+
last_expression = rb_funcall2(((VALUE*)method_arguments)[2], #{intern_num mname.to_sym}, ((int*)method_arguments)[0], ((VALUE**)method_arguments)[1]);", true, "method_arguments"
|
1536
|
+
};
|
1496
1537
|
|
1497
|
-
|
1498
|
-
|
1538
|
+
} else {
|
1539
|
+
#{
|
1540
|
+
if return_on_block_call
|
1541
|
+
"*block_call = 1;
|
1542
|
+
return Qnil;
|
1543
|
+
"
|
1544
|
+
else
|
1545
|
+
"
|
1546
|
+
return #{
|
1547
|
+
protected_block "
|
1548
|
+
#{@block_struct} *pblock;
|
1549
|
+
pblock = (typeof(pblock))( ((VALUE*)method_arguments)[3] );
|
1550
|
+
last_expression = rb_iterate(
|
1551
|
+
#{anonymous_function{|name_|
|
1552
|
+
"
|
1553
|
+
static VALUE #{name_} (VALUE data) {
|
1554
|
+
VALUE* method_arguments = (VALUE*)data;
|
1555
|
+
return rb_funcall2(((VALUE*)method_arguments)[2], #{intern_num mname.to_sym}, ((int*)method_arguments)[0], ((VALUE**)method_arguments)[1]);
|
1556
|
+
}
|
1557
|
+
"
|
1558
|
+
}},
|
1559
|
+
(VALUE)method_arguments,
|
1560
|
+
|
1561
|
+
#{anonymous_function{|name_|
|
1562
|
+
"
|
1563
|
+
static VALUE #{name_} (VALUE arg_, VALUE param, int argc, VALUE* argv) {
|
1564
|
+
#{@block_struct}* pblock = (void*)param;
|
1565
|
+
|
1566
|
+
if (pblock->proc != Qnil) {
|
1567
|
+
VALUE arg;
|
1568
|
+
#{
|
1569
|
+
# TODO: access directly to argc and argv for optimal execution
|
1570
|
+
if RUBY_VERSION =~ /^1\.9/
|
1571
|
+
"
|
1572
|
+
if (TYPE(arg_) == T_ARRAY) {
|
1573
|
+
if (_RARRAY_LEN(arg_) <= 1) {
|
1574
|
+
arg = rb_ary_new4(argc,argv);
|
1575
|
+
} else {
|
1576
|
+
arg = arg_;
|
1577
|
+
}
|
1578
|
+
} else {
|
1579
|
+
arg = rb_ary_new4(argc,argv);
|
1580
|
+
}
|
1581
|
+
"
|
1582
|
+
else
|
1583
|
+
"arg = arg_;"
|
1584
|
+
end
|
1585
|
+
}
|
1586
|
+
|
1587
|
+
return rb_proc_call(pblock->proc, arg);
|
1588
|
+
|
1589
|
+
} else {
|
1590
|
+
#{
|
1591
|
+
# TODO: access directly to argc and argv for optimal execution
|
1592
|
+
if RUBY_VERSION =~ /^1\.9/
|
1593
|
+
"return ((VALUE(*)(int,VALUE*,VALUE,VALUE))pblock->block_function_address)(argc,argv,(VALUE)pblock->block_function_param,(VALUE)0);"
|
1594
|
+
else
|
1595
|
+
"return Qnil;"
|
1596
|
+
end
|
1597
|
+
}
|
1598
|
+
}
|
1599
|
+
|
1600
|
+
}
|
1601
|
+
"
|
1602
|
+
}},
|
1603
|
+
(VALUE)pblock
|
1604
|
+
);
|
1605
|
+
", true, "method_arguments"
|
1606
|
+
};
|
1607
|
+
"
|
1608
|
+
end
|
1609
|
+
}
|
1610
|
+
}
|
1611
|
+
"
|
1612
|
+
else
|
1613
|
+
"
|
1614
|
+
rb_raise(rb_eRuntimeError, \"Error: invalid dynamic call for defn\");
|
1615
|
+
return Qnil;
|
1616
|
+
"
|
1617
|
+
end
|
1499
1618
|
}
|
1619
|
+
}
|
1500
1620
|
"
|
1501
|
-
|
1502
|
-
init_extra << "
|
1503
|
-
// ruby, wrap rb_funcall
|
1504
|
-
#{name} = (void*)#{pureruby_wrapper};
|
1505
|
-
"
|
1506
|
-
end
|
1507
|
-
|
1508
|
-
name
|
1621
|
+
}
|
1509
1622
|
end
|
1510
1623
|
|
1511
1624
|
def intern_num(symbol)
|
@@ -1523,6 +1636,20 @@ fastruby_local_next:
|
|
1523
1636
|
|
1524
1637
|
name
|
1525
1638
|
end
|
1639
|
+
|
1640
|
+
def reserve_table(size, argument_count)
|
1641
|
+
name = "glb_table" + rand(1000000000).to_s
|
1642
|
+
|
1643
|
+
extra_code << "
|
1644
|
+
static struct {
|
1645
|
+
VALUE argument_type[#{argument_count}];
|
1646
|
+
void* address;
|
1647
|
+
int argc;
|
1648
|
+
} #{name}[#{size}];
|
1649
|
+
"
|
1650
|
+
|
1651
|
+
name
|
1652
|
+
end
|
1526
1653
|
|
1527
1654
|
def add_global_name(ctype, default)
|
1528
1655
|
name = "glb" + rand(1000000000).to_s
|