fastruby 0.0.17 → 0.0.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/CHANGELOG +10 -0
  2. data/Rakefile +4 -2
  3. data/benchmarks/benchmark.rb +20 -44
  4. data/benchmarks/benchmark.rb~ +47 -0
  5. data/benchmarks/benchmark2.rb +19 -45
  6. data/benchmarks/benchmark2.rb~ +46 -0
  7. data/benchmarks/benchmark3.rb +19 -45
  8. data/benchmarks/benchmark3.rb~ +46 -0
  9. data/benchmarks/benchmark4.rb +30 -65
  10. data/benchmarks/benchmark4.rb~ +61 -0
  11. data/benchmarks/benchmark5.rb +25 -55
  12. data/benchmarks/benchmark5.rb~ +54 -0
  13. data/benchmarks/benchmark6.rb +19 -40
  14. data/benchmarks/benchmark6.rb~ +41 -0
  15. data/benchmarks/benchmark7.rb +23 -52
  16. data/benchmarks/benchmark7.rb~ +48 -0
  17. data/ext/fastruby_base/fastruby_base.inl +1 -0
  18. data/lib/fastruby/builder.rb +128 -76
  19. data/lib/fastruby/cache/cache.rb +9 -5
  20. data/lib/fastruby/fastruby_sexp.rb +18 -0
  21. data/lib/fastruby/inliner/inliner.rb +68 -0
  22. data/lib/fastruby/inliner/modules/call.rb +150 -0
  23. data/lib/fastruby/inliner/modules/recursive.rb +35 -0
  24. data/lib/fastruby/object.rb +17 -32
  25. data/lib/fastruby/reductor/modules/case.rb +49 -0
  26. data/lib/{fastruby.rb~ → fastruby/reductor/modules/for.rb} +11 -13
  27. data/lib/fastruby/reductor/modules/nontree.rb +31 -0
  28. data/lib/fastruby/reductor/modules/recursive.rb +31 -0
  29. data/lib/fastruby/reductor/reductor.rb +39 -0
  30. data/lib/fastruby/set_tree.rb +7 -1
  31. data/lib/fastruby/sexp_extension.rb +6 -0
  32. data/lib/fastruby/translator/modules/block.rb +4 -4
  33. data/lib/fastruby/translator/modules/call.rb +9 -26
  34. data/lib/fastruby/translator/modules/defn.rb +5 -3
  35. data/lib/fastruby/translator/modules/directive.rb +42 -0
  36. data/lib/fastruby/translator/modules/exceptions.rb +12 -30
  37. data/lib/fastruby/translator/modules/flow.rb +33 -83
  38. data/lib/fastruby/translator/modules/iter.rb +4 -7
  39. data/lib/fastruby/translator/modules/literal.rb +11 -25
  40. data/lib/fastruby/translator/modules/logical.rb +5 -3
  41. data/lib/fastruby/translator/modules/method_group.rb +4 -3
  42. data/lib/fastruby/translator/modules/nonlocal.rb +7 -5
  43. data/lib/fastruby/translator/modules/static.rb +242 -0
  44. data/lib/fastruby/translator/modules/variable.rb +16 -9
  45. data/lib/fastruby/translator/scope_mode_helper.rb +2 -27
  46. data/lib/fastruby/translator/translator.rb +131 -60
  47. data/lib/fastruby/translator/translator_modules.rb +6 -2
  48. data/lib/fastruby.rb +1 -1
  49. data/spec/reductor/base_spec.rb +46 -0
  50. data/spec/ruby/base_spec.rb~ +394 -0
  51. data/spec/ruby/block/arguments_spec.rb~ +214 -0
  52. data/spec/ruby/block/proc_as_block_spec.rb~ +23 -0
  53. data/spec/ruby/block/retry_spec.rb~ +43 -0
  54. data/spec/ruby/block_spec.rb~ +520 -0
  55. data/spec/ruby/defn/replacement_spec.rb~ +102 -0
  56. data/spec/ruby/integrity_spec.rb~ +40 -0
  57. data/spec/ruby/singleton_spec.rb~ +76 -0
  58. data/spec/scope_mode/base_spec.rb +14 -5
  59. data/spec/scope_mode/block_spec.rb +18 -9
  60. data/spec/scope_mode/call_spec.rb +11 -2
  61. data/spec/scope_mode/exception_spec.rb +11 -2
  62. data/spec/scope_mode/flow_spec.rb +18 -8
  63. data/spec/scope_mode/optimization_spec.rb +21 -13
  64. data/spec/static/base_spec.rb +54 -0
  65. data/spec/static/flow_spec.rb +48 -0
  66. data/spec/static/operator_spec.rb +104 -0
  67. metadata +58 -8
@@ -26,6 +26,7 @@ require "fastruby/set_tree"
26
26
  require "fastruby/exceptions"
27
27
  require "fastruby/translator/translator_modules"
28
28
  require "fastruby/translator/scope_mode_helper"
29
+ require "define_method_handler"
29
30
 
30
31
  module FastRuby
31
32
  class Context
@@ -39,12 +40,66 @@ module FastRuby
39
40
  attr_reader :init_extra
40
41
  attr_reader :extra_code
41
42
 
42
- TranslatorModules.instance.load_under(FastRuby.fastruby_load_path + "/fastruby/translator/modules/")
43
- TranslatorModules.instance.modls.each do |modl|
44
- include modl
43
+ class Value
44
+ attr_accessor :value
45
+ def initialize(v); @value = v; end
46
+ end
47
+
48
+ def self.define_translator_for(ntype, options = {}, &blk)
49
+ condition_blk = proc do |*x|
50
+ tree = x.first; tree.node_type == ntype
51
+ end
52
+
53
+ if options[:arity]
54
+ if options[:arity] == 1
55
+ condition_blk = proc do |*x|
56
+ tree = x.first; x.size == 1 and tree.node_type == ntype
57
+ end
58
+ end
59
+ end
60
+
61
+ define_method_handler(:to_c, options, &blk).condition &condition_blk
62
+ end
63
+
64
+ define_method_handler(:to_c, :priority => 10000){|*x|
65
+ "Qnil"
66
+ }.condition{|*x| x.size == 1 and (not x.first)}
67
+
68
+ define_method_handler(:to_c, :priority => 1000){|tree, result_var|
69
+ "#{result_var} = #{to_c(tree)};"
70
+ }.condition{|*x| x.size == 2 and (not x.first)}
71
+
72
+ define_method_handler(:to_c, :priority => -9000){ |tree, result_var|
73
+ "#{result_var} = #{to_c(tree)};"
74
+ }.condition{|*x| x.size == 2 }
75
+
76
+ define_method_handler(:to_c, :priority => -10000) do |tree, result_var=nil|
77
+ raise "undefined translator for node type :#{tree.node_type}"
78
+ end
79
+
80
+ define_method_handler(:initialize_to_c){|*x|}.condition{|*x|false}
81
+
82
+ define_translator_for(:call, :priority => 100){ |tree, result_var=nil|
83
+ tree[2] = :fastruby_require
84
+ to_c(tree)
85
+ }.condition{|*x|
86
+ tree = x.first; tree.node_type == :call && tree[2] == :require
87
+ }
88
+
89
+ define_method_handler(:infer_value, :priority => -1000) do |tree|
90
+ nil
91
+ end
92
+
93
+ TranslatorModules.instance.each_under(FastRuby.fastruby_load_path + "/fastruby/translator/modules/") do |path|
94
+ groupname = path.split("/").last.split(".").first.to_sym
95
+ handler_scope(:group => groupname) do
96
+ require path
97
+ end
45
98
  end
46
99
 
47
100
  def initialize(common_func = true)
101
+ initialize_to_c
102
+
48
103
  @infer_lvar_map = Hash.new
49
104
  @no_cache = false
50
105
  @extra_code = ""
@@ -183,22 +238,32 @@ module FastRuby
183
238
  end
184
239
  end
185
240
 
186
- def to_c(tree, result_variable = nil)
187
- return "Qnil" unless tree
188
-
189
- mname = "to_c_" + tree[0].to_s
190
-
191
- if result_variable
192
- if method(mname).arity == 1
193
- "#{result_variable} = #{send(mname, tree)};\n"
194
- else
195
- send(mname, tree, result_variable)
196
- end
241
+
242
+ def _raise(class_tree, message_tree = nil)
243
+ class_tree = to_c class_tree unless class_tree.instance_of? String
244
+
245
+ if message_tree.instance_of? String
246
+ message_tree = "rb_str_new2(#{message_tree.inspect})"
197
247
  else
198
- send(mname, tree)
248
+ message_tree = to_c message_tree
249
+ end
250
+
251
+ if message_tree
252
+ return inline_block("
253
+ pframe->thread_data->exception = rb_funcall(#{class_tree}, #{intern_num :exception},1,#{message_tree});
254
+ longjmp(pframe->jmp, FASTRUBY_TAG_RAISE);
255
+ return Qnil;
256
+ ")
257
+ else
258
+ return inline_block("
259
+ pframe->thread_data->exception = rb_funcall(#{class_tree}, #{intern_num :exception},0);
260
+ longjmp(pframe->jmp, FASTRUBY_TAG_RAISE);
261
+ return Qnil;
262
+ ")
199
263
  end
200
- end
201
264
 
265
+ end
266
+
202
267
  def anonymous_function(*x)
203
268
 
204
269
  name = "anonymous" + rand(10000000).to_s
@@ -280,7 +345,7 @@ module FastRuby
280
345
 
281
346
  extra_code << "
282
347
  static VALUE #{@alt_method_name}(VALUE self__);
283
- static VALUE main_proc_call(VALUE self__, VALUE class_self_) {
348
+ static VALUE main_proc_call(VALUE self__, VALUE signature, VALUE class_self_) {
284
349
  #{@alt_method_name}(class_self_);
285
350
  return Qnil;
286
351
  }
@@ -290,23 +355,22 @@ module FastRuby
290
355
  init_extra << "
291
356
  {
292
357
  VALUE newproc = rb_funcall(rb_cObject,#{intern_num :new},0);
293
- rb_define_singleton_method(newproc, \"call\", main_proc_call, 1);
358
+ rb_define_singleton_method(newproc, \"call\", main_proc_call, 2);
294
359
  rb_gv_set(\"$last_obj_proc\", newproc);
295
-
296
360
  }
297
361
  "
298
362
  end
299
363
  end
300
364
 
301
- def define_method_at_init(klass,method_name, size, signature)
302
- init_extra << "
303
- {
365
+ def define_method_at_init(method_name, size, signature)
366
+ extra_code << "
367
+ static VALUE main_proc_call(VALUE self__, VALUE signature, VALUE class_self_) {
304
368
  VALUE method_name = rb_funcall(
305
369
  #{literal_value FastRuby},
306
370
  #{intern_num :make_str_signature},
307
371
  2,
308
372
  #{literal_value method_name},
309
- #{literal_value signature}
373
+ signature
310
374
  );
311
375
 
312
376
  ID id = rb_intern(RSTRING_PTR(method_name));
@@ -315,12 +379,12 @@ module FastRuby
315
379
  #{literal_value FastRuby},
316
380
  #{intern_num :set_builder_module},
317
381
  1,
318
- #{literal_value klass}
382
+ class_self_
319
383
  );
320
384
 
321
385
  VALUE rb_method_hash;
322
386
  void** address = 0;
323
- rb_method_hash = rb_funcall(#{literal_value klass}, #{intern_num :method_hash},1,#{literal_value method_name});
387
+ rb_method_hash = rb_funcall(class_self_, #{intern_num :method_hash},1,#{literal_value method_name});
324
388
 
325
389
  if (rb_method_hash != Qnil) {
326
390
  VALUE tmp = rb_hash_aref(rb_method_hash, PTR2NUM(id));
@@ -335,15 +399,25 @@ module FastRuby
335
399
  *address = #{alt_method_name};
336
400
 
337
401
  rb_funcall(
338
- #{literal_value klass},
402
+ class_self_,
339
403
  #{intern_num :register_method_value},
340
404
  3,
341
405
  #{literal_value method_name},
342
406
  PTR2NUM(id),
343
407
  PTR2NUM(address)
344
408
  );
409
+
410
+ return Qnil;
345
411
  }
346
412
  "
413
+
414
+ init_extra << "
415
+ {
416
+ VALUE newproc = rb_funcall(rb_cObject,#{intern_num :new},0);
417
+ rb_define_singleton_method(newproc, \"call\", main_proc_call, 2);
418
+ rb_gv_set(\"$last_obj_proc\", newproc);
419
+ }
420
+ "
347
421
  end
348
422
 
349
423
  def to_c_method(tree, signature = nil)
@@ -359,7 +433,7 @@ module FastRuby
359
433
  block_argument = tree[3].find{|x| x.to_s[0] == ?&}
360
434
  impl_tree = tree[4][1]
361
435
  end
362
-
436
+
363
437
  args_tree = original_args_tree.select{|x| x.to_s[0] != ?&}
364
438
 
365
439
  initialize_method_structs(original_args_tree)
@@ -1073,22 +1147,31 @@ fastruby_local_next:
1073
1147
  end
1074
1148
 
1075
1149
  pureruby_wrapper = anonymous_function{ |funcname| "
1076
- static VALUE #{funcname}(VALUE self,void* block,void* frame#{strargs_signature}){
1150
+ static VALUE #{funcname}(VALUE self,void* block,void* frame, int argc, VALUE* argv){
1077
1151
  #{@frame_struct}* pframe = frame;
1078
- VALUE method_arguments[#{args_tree.size}] = {#{toprocstrargs}};
1079
-
1152
+ VALUE method_arguments[3];
1153
+
1154
+ method_arguments[0] = (VALUE)argc;
1155
+ method_arguments[1] = (VALUE)argv;
1156
+ method_arguments[2] = (VALUE)self;
1157
+
1080
1158
  return #{
1081
- protected_block "last_expression = rb_funcall(((VALUE*)method_arguments)[0], #{intern_num mname.to_sym}, #{args_tree.size-1}#{inprocstrargs});", false, "method_arguments"
1159
+ protected_block "last_expression = rb_funcall2(((VALUE*)method_arguments)[2], #{intern_num mname.to_sym}, ((int*)method_arguments)[0], ((VALUE**)method_arguments)[1]);", false, "method_arguments"
1082
1160
  };
1083
1161
  }
1084
1162
  "
1085
1163
  }
1086
1164
 
1087
1165
  generic_wrapper = anonymous_function{ |funcname| "
1088
- static VALUE #{funcname}(VALUE self,void* block,void* frame#{strargs_signature}){
1166
+ static VALUE #{funcname}(VALUE self,void* block,void* frame, int argc, VALUE* argv){
1089
1167
 
1090
1168
  #{@frame_struct}* pframe = frame;
1091
- VALUE method_arguments[#{args_tree.size+1}] = {#{toprocstrargs},(VALUE)block};
1169
+ VALUE method_arguments[4];
1170
+
1171
+ method_arguments[0] = (VALUE)argc;
1172
+ method_arguments[1] = (VALUE)argv;
1173
+ method_arguments[2] = (VALUE)self;
1174
+ method_arguments[3] = (VALUE)block;
1092
1175
 
1093
1176
  void* fptr = 0;
1094
1177
 
@@ -1106,40 +1189,30 @@ fastruby_local_next:
1106
1189
 
1107
1190
  fptr = *#{address_name};
1108
1191
 
1109
- #{
1110
- if args_tree.size < 25
1111
- "
1112
1192
  if (fptr == 0) {
1113
1193
  fptr = *#{cfunc_address_name};
1114
1194
  if (fptr != 0) {
1115
- VALUE params[2] = {self,PTR2NUM(#{args_tree.size-1})};
1116
- return ( (VALUE(*)(#{value_cast})) (fptr) )((VALUE)params,(VALUE)block,(VALUE)frame#{inprocstrargs});
1195
+ return ( (VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*) ) (fptr) )(self,(VALUE)block,(VALUE)frame, argc, argv);
1117
1196
  }
1118
1197
  }
1119
- "
1120
- end
1121
- }
1122
-
1198
+
1123
1199
  if (fptr == 0) {
1124
1200
  if (block==0) {
1125
1201
  return #{
1126
- protected_block "last_expression = rb_funcall(((VALUE*)method_arguments)[0], #{intern_num mname.to_sym}, #{args_tree.size-1}#{inprocstrargs});", false, "method_arguments"
1202
+ protected_block "last_expression = rb_funcall2(((VALUE*)method_arguments)[2], #{intern_num mname.to_sym}, ((int*)method_arguments)[0], ((VALUE**)method_arguments)[1]);", false, "method_arguments"
1127
1203
  };
1128
1204
 
1129
1205
  } else {
1130
1206
  return #{
1131
1207
  protected_block "
1132
1208
  #{@block_struct} *pblock;
1133
- pblock = (typeof(pblock))( ((VALUE*)method_arguments)[#{args_tree.size}] );
1209
+ pblock = (typeof(pblock))( ((VALUE*)method_arguments)[3] );
1134
1210
  last_expression = rb_iterate(
1135
1211
  #{anonymous_function{|name|
1136
1212
  "
1137
1213
  static VALUE #{name} (VALUE data) {
1138
1214
  VALUE* method_arguments = (VALUE*)data;
1139
- return rb_funcall(
1140
- ((VALUE*)method_arguments)[0],
1141
- #{intern_num mname.to_sym},
1142
- #{args_tree.size-1}#{inprocstrargs});
1215
+ return rb_funcall2(((VALUE*)method_arguments)[2], #{intern_num mname.to_sym}, ((int*)method_arguments)[0], ((VALUE**)method_arguments)[1]);
1143
1216
  }
1144
1217
  "
1145
1218
  }},
@@ -1180,19 +1253,20 @@ fastruby_local_next:
1180
1253
  }
1181
1254
 
1182
1255
  } else {
1183
- return ( (VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*)) (fptr) )(self,(VALUE)block,(VALUE)frame,#{args_tree.size-1},method_arguments+1);
1256
+ return ( (VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*)) (fptr) )(self,(VALUE)block,(VALUE)frame,argc,argv);
1184
1257
  }
1185
1258
  }
1186
1259
  "
1187
1260
  }
1188
1261
 
1189
1262
 
1263
+ cfuncall1inprocargs = (0..args_tree.size-2).map{|x| "argv[#{x}]"}.join(",")
1264
+ cfuncall1inprocargs = ","+cfuncall1inprocargs if cfuncall1inprocargs != ""
1265
+
1190
1266
  cfunc_value_cast = (["VALUE"]*args_tree.size).join(",")
1191
1267
  cfunc_wrapper = anonymous_function{ |funcname| "
1192
- static VALUE #{funcname}(VALUE* params, void* block,void* frame#{strargs_signature}){
1193
- VALUE self = params[0];
1194
- VALUE method_arguments[#{args_tree.size}] = {#{toprocstrargs}};
1195
- return ( (VALUE(*)(#{cfunc_value_cast})) (#{cfunc_real_address_name}) )(self#{inprocstrargs});
1268
+ static VALUE #{funcname}(VALUE self, void* block,void* frame, int argc, VALUE* argv){
1269
+ return ( (VALUE(*)(#{cfunc_value_cast})) (#{cfunc_real_address_name}) )(self#{cfuncall1inprocargs});
1196
1270
  }
1197
1271
  "
1198
1272
  }
@@ -1201,18 +1275,15 @@ fastruby_local_next:
1201
1275
  strargs_signature = (0..25).map{|x| "VALUE arg#{x}"}.join(",")
1202
1276
 
1203
1277
  cfunc_wrapper_1 = anonymous_function{ |funcname| "
1204
- static VALUE #{funcname}(VALUE* params, void* block,void* frame, #{strargs_signature}){
1205
- VALUE self = params[0];
1206
- VALUE method_arguments[26] = {#{toprocstrargs}};
1207
- return ( (VALUE(*)(int, VALUE*, VALUE)) (#{cfunc_real_address_name}) )(NUM2ULONG(params[1]),method_arguments,self);
1278
+ static VALUE #{funcname}(VALUE self, void* block,void* frame, int argc, VALUE* argv){
1279
+ return ( (VALUE(*)(int, VALUE*, VALUE)) (#{cfunc_real_address_name}) )(argc,argv,self);
1208
1280
  }
1209
1281
  "
1210
1282
  }
1211
1283
 
1212
1284
  cfunc_wrapper_2 = anonymous_function{ |funcname| "
1213
- static VALUE #{funcname}(VALUE* params, void* block,void* frame, #{strargs_signature}){
1214
- VALUE self = params[0];
1215
- VALUE args = rb_ary_new3(NUM2ULONG(params[1]),#{toprocstrargs});
1285
+ static VALUE #{funcname}(VALUE self, void* block,void* frame, int argc, VALUE* argv){
1286
+ VALUE args = rb_ary_new3(argc, argv);
1216
1287
  return ( (VALUE(*)(VALUE,VALUE)) (#{cfunc_real_address_name}) )(self,args);
1217
1288
  }
1218
1289
  "
@@ -34,11 +34,15 @@ module FastRuby
34
34
  @modls << modl
35
35
  end
36
36
 
37
- def load_under(dir)
37
+ def each_under(dir)
38
38
  Dir.glob(dir + "/*.rb") do |x|
39
- require x
39
+ yield x
40
40
  end
41
41
  end
42
+
43
+ def load_under(dir)
44
+ each_under(dir, &method(:require))
45
+ end
42
46
  end
43
47
  end
44
48
 
data/lib/fastruby.rb CHANGED
@@ -32,5 +32,5 @@ class Object
32
32
  end
33
33
 
34
34
  module FastRuby
35
- VERSION = "0.0.17" unless defined? FastRuby::VERSION
35
+ VERSION = "0.0.18" unless defined? FastRuby::VERSION
36
36
  end
@@ -0,0 +1,46 @@
1
+ require "fastruby"
2
+ require "fastruby/reductor/reductor"
3
+ require "fastruby/sexp_extension"
4
+ require "ruby_parser"
5
+
6
+ describe FastRuby, "fastruby" do
7
+
8
+ def self.test_normal_tree(code)
9
+ unmodified_tree = FastRuby::FastRubySexp.from_sexp RubyParser.new.parse code
10
+ it "tree for source #{code} should not be changed by reductor" do
11
+ obtained_tree = FastRuby::Reductor.new.reduce unmodified_tree
12
+ obtained_tree.should be == unmodified_tree
13
+ end
14
+ end
15
+
16
+ it "should reduce for statements into each calls" do
17
+ reductor = FastRuby::Reductor.new
18
+
19
+ original_tree = fs(:for, fs(:call, nil, :b, fs(:arglist)), fs(:lasgn, :a), fs(:call, nil, :c, fs(:arglist)))
20
+ expected_tree = fs(:iter, fs(:call, fs(:call, nil, :b, fs(:arglist)), :each, fs(:arglist)), fs(:lasgn, :a), fs(:call, nil, :c, fs(:arglist)))
21
+ obtained_tree = reductor.reduce original_tree
22
+
23
+ obtained_tree.should be == expected_tree
24
+ end
25
+
26
+ test_normal_tree "a.foo(b)"
27
+ test_normal_tree "if (x); y; else; z; end"
28
+
29
+ it "should reduce call statements into if arrays" do
30
+ reductor = FastRuby::Reductor.new
31
+
32
+ original_tree = fs(:case,
33
+ fs(:call, nil, :a, fs(:arglist)),
34
+ fs(:when, fs(:array, fs(:call, nil, :b, fs(:arglist))), fs(:call, nil, :c, fs(:arglist))),
35
+ nil)
36
+
37
+ obtained_tree = reductor.reduce original_tree
38
+
39
+ obtained_tree.node_type.should be == :block
40
+ obtained_tree[1].node_type.should be == :lasgn
41
+ obtained_tree[1].last.should be == s(:call, nil, :a, s(:arglist)).to_fastruby_sexp
42
+ obtained_tree[2].node_type.should be == :if
43
+ obtained_tree[2][1].node_type.should be == :or
44
+ obtained_tree[2][2].should be == original_tree.find_tree(:when).last
45
+ end
46
+ end