fastruby 0.0.17 → 0.0.18

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.
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
@@ -2,81 +2,51 @@ require "rubygems"
2
2
  require "fastruby"
3
3
 
4
4
  class X
5
- fastruby "
6
- def bar
7
- end
8
- "
9
-
10
- fastruby "
11
- def foo
12
- yield(self)
13
- end
14
- "
15
- end
16
-
17
- class Y
18
- fastruby "
19
- def bar(x)
20
- i = 1000000
21
-
22
- lvar_type(i,Fixnum)
23
- lvar_type(x2,X)
24
-
25
- ret = 0
26
- while i > 0
27
- x.foo do |x2|
28
- x2.bar
29
- end
30
- i = i - 1
31
- end
32
- 0
33
- end
34
-
35
- "
36
- end
37
-
38
- class X2
39
5
  def bar
40
6
  end
41
7
 
42
- def foo
8
+ def foo
43
9
  yield(self)
44
10
  end
45
11
  end
46
12
 
47
- class Y2
48
- def bar(x)
49
- i = 1000000
13
+ class Y
14
+ def bar(x)
15
+ i = 1000000
50
16
 
51
- ret = 0
52
- while i > 0
53
- x.foo do |x2|
54
- x2.bar
55
- end
56
- i = i - 1
17
+ lvar_type(:i,Fixnum)
18
+ lvar_type(:x2,X)
19
+
20
+ ret = 0
21
+ while i > 0
22
+ x.foo do |x2|
23
+ x2.bar
57
24
  end
58
- 0
25
+ i = i - 1
59
26
  end
27
+ 0
28
+ end
60
29
  end
61
30
 
62
-
63
31
  x = X.new
64
32
  y = Y.new
65
- y2 = Y2.new
66
- x2 = X2.new
67
-
68
- Y.build([Y,X],:bar)
69
- X.build([X],:foo)
70
- X.build([X],:bar)
71
33
 
72
34
  require 'benchmark'
73
35
 
74
36
  Benchmark::bm(20) do |b|
75
- b.report("fastruby") do
37
+ b.report("ruby") do
76
38
  y.bar(x)
77
39
  end
78
40
 
79
- b.report("ruby") do
80
- y2.bar(x2)
41
+ Y.optimize(:bar)
42
+ X.optimize(:foo)
43
+ X.optimize(:bar)
44
+
45
+ Y.build([Y,X],:bar)
46
+ X.build([X],:foo)
47
+ X.build([X],:bar)
48
+
49
+ b.report("fastruby") do
50
+ y.bar(x)
81
51
  end
82
52
  end
@@ -0,0 +1,54 @@
1
+ require "rubygems"
2
+ require "fastruby"
3
+
4
+ def lvar_type(*x); end
5
+
6
+ class X
7
+ def bar
8
+ end
9
+
10
+ def foo
11
+ yield(self)
12
+ end
13
+ end
14
+
15
+ class Y
16
+ def bar(x)
17
+ i = 1000000
18
+
19
+ lvar_type(:i,Fixnum)
20
+ lvar_type(:x2,X)
21
+
22
+ ret = 0
23
+ while i > 0
24
+ x.foo do |x2|
25
+ x2.bar
26
+ end
27
+ i = i - 1
28
+ end
29
+ 0
30
+ end
31
+ end
32
+
33
+ x = X.new
34
+ y = Y.new
35
+
36
+ require 'benchmark'
37
+
38
+ Benchmark::bm(20) do |b|
39
+ b.report("ruby") do
40
+ y.bar(x)
41
+ end
42
+
43
+ Y.optimize(:bar)
44
+ X.optimize(:foo)
45
+ X.optimize(:bar)
46
+
47
+ Y.build([Y,X],:bar)
48
+ X.build([X],:foo)
49
+ X.build([X],:bar)
50
+
51
+ b.report("fastruby") do
52
+ y.bar(x)
53
+ end
54
+ end
@@ -1,64 +1,43 @@
1
1
  require "rubygems"
2
2
  require "fastruby"
3
3
 
4
- class X
5
- fastruby '
6
- def foo
7
- "65535".to_i
8
- end
9
- '
10
- end
11
-
12
- class Y
13
- fastruby "
14
- def bar(x)
15
- i = 1000000
16
- lvar_type(i,Fixnum)
17
-
18
- while i > 0
19
- x.foo
20
- i = i - 1
21
- end
22
- 0
23
- end
4
+ def lvar_type(*x); end
24
5
 
25
- "
26
- end
27
-
28
- class X2
6
+ class X
29
7
  def foo
30
8
  "65535".to_i
31
9
  end
32
10
  end
33
11
 
34
- class Y2
35
- def bar(x)
36
- i = 1000000
12
+ class Y
13
+ def bar(x)
14
+ i = 1000000
15
+ lvar_type(i,Fixnum)
37
16
 
38
- while i > 0
39
- x.foo
40
- i = i - 1
41
- end
42
- 0
17
+ while i > 0
18
+ x.foo
19
+ i = i - 1
43
20
  end
21
+ 0
22
+ end
44
23
  end
45
24
 
46
-
47
25
  x = X.new
48
26
  y = Y.new
49
- y2 = Y2.new
50
- x2 = X2.new
51
-
52
- Y.build([Y,X],:bar)
53
27
 
54
28
  require 'benchmark'
55
29
 
56
30
  Benchmark::bm(20) do |b|
57
- b.report("fastruby") do
31
+ b.report("ruby") do
58
32
  y.bar(x)
59
33
  end
60
34
 
61
- b.report("ruby") do
62
- y2.bar(x2)
35
+ X.optimize(:foo)
36
+ Y.optimize(:bar)
37
+ X.build([X],:foo)
38
+ Y.build([Y,X],:bar)
39
+
40
+ b.report("fastruby") do
41
+ y.bar(x)
63
42
  end
64
43
  end
@@ -0,0 +1,41 @@
1
+ require "rubygems"
2
+ require "fastruby"
3
+
4
+ class X
5
+ def foo
6
+ "65535".to_i
7
+ end
8
+ end
9
+
10
+ class Y
11
+ def bar(x)
12
+ i = 1000000
13
+ lvar_type(i,Fixnum)
14
+
15
+ while i > 0
16
+ x.foo
17
+ i = i - 1
18
+ end
19
+ 0
20
+ end
21
+ end
22
+
23
+ x = X.new
24
+ y = Y.new
25
+
26
+ require 'benchmark'
27
+
28
+ Benchmark::bm(20) do |b|
29
+ b.report("ruby") do
30
+ y.bar(x)
31
+ end
32
+
33
+ X.optimize(:foo)
34
+ Y.optimize(:bar)
35
+ X.build([X],:foo)
36
+ Y.build([Y,X],:bar)
37
+
38
+ b.report("fastruby") do
39
+ y.bar(x)
40
+ end
41
+ end
@@ -2,76 +2,47 @@ require "rubygems"
2
2
  require "fastruby"
3
3
 
4
4
  class X
5
- fastruby "
6
- def factorial(n)
7
- if n > 1
8
- n * factorial((n-1).infer(Fixnum))
9
- else
10
- 1
11
- end
12
- end
13
- "
14
- end
15
-
16
- class Y
17
- fastruby "
18
- def bar(x)
19
- i = 100000
20
-
21
- lvar_type(i,Fixnum)
22
-
23
- ret = 0
24
- while i > 0
25
- x.factorial(20)
26
- i = i - 1
27
- end
28
- return ret
29
- end
30
-
31
- "
32
- end
33
-
34
- class X2
35
- def factorial(n)
5
+ def factorial(n)
36
6
  if n > 1
37
- n * factorial(n-1)
7
+ n * factorial((n-1).infer(Fixnum))
38
8
  else
39
9
  1
40
10
  end
41
11
  end
42
12
  end
43
13
 
44
- class Y2
45
- def bar(x)
46
- i = 100000
14
+ class Y
15
+ def bar(x)
16
+ i = 100000
17
+
18
+ lvar_type(i,Fixnum)
47
19
 
48
- ret = 0
49
- while i > 0
50
- x.factorial(20)
51
- i = i - 1
52
- end
53
- return ret
54
- end
55
-
20
+ ret = 0
21
+ while i > 0
22
+ x.factorial(20)
23
+ i = i - 1
24
+ end
25
+ return ret
26
+ end
56
27
  end
57
28
 
58
-
59
29
  x = X.new
60
30
  y = Y.new
61
- y2 = Y2.new
62
- x2 = X2.new
63
-
64
- Y.build([Y,X],:bar)
65
31
 
66
32
  require 'benchmark'
67
33
 
68
34
  Benchmark::bm(20) do |b|
69
-
70
- b.report("fastruby") do
35
+ b.report("ruby") do
71
36
  y.bar(x)
72
37
  end
73
38
 
74
- b.report("ruby") do
75
- y2.bar(x2)
39
+ X.optimize(:factorial)
40
+ Y.optimize(:bar)
41
+ X.build([X],:factorial)
42
+ Y.build([Y,X],:bar)
43
+
44
+ b.report("fastruby") do
45
+ y.bar(x)
76
46
  end
77
47
  end
48
+
@@ -0,0 +1,48 @@
1
+ require "rubygems"
2
+ require "fastruby"
3
+
4
+ class X
5
+ def factorial(n)
6
+ if n > 1
7
+ n * factorial(1)
8
+ else
9
+ 1
10
+ end
11
+ end
12
+ end
13
+
14
+ class Y
15
+ def bar(x)
16
+ i = 100000
17
+
18
+ lvar_type(i,Fixnum)
19
+
20
+ ret = 0
21
+ while i > 0
22
+ x.factorial(20)
23
+ i = i - 1
24
+ end
25
+ return ret
26
+ end
27
+ end
28
+
29
+ x = X.new
30
+ y = Y.new
31
+
32
+ require 'benchmark'
33
+
34
+ Benchmark::bm(20) do |b|
35
+ b.report("ruby") do
36
+ y.bar(x)
37
+ end
38
+
39
+ X.optimize(:factorial)
40
+ Y.optimize(:bar)
41
+ X.build([X],:factorial)
42
+ Y.build([Y,X],:bar)
43
+
44
+ b.report("fastruby") do
45
+ y.bar(x)
46
+ end
47
+ end
48
+
@@ -412,6 +412,7 @@ static VALUE fastruby_method_tree_pointer(VALUE self) {
412
412
 
413
413
  static VALUE fastruby_method_tree_eq(VALUE self, VALUE val) {
414
414
  VALUE* tree_pointer = (VALUE*)FIX2LONG(fastruby_method_tree_pointer(self));
415
+ rb_ivar_set(self, rb_intern("__current_tree"), val);
415
416
  *tree_pointer = val;
416
417
  return Qnil;
417
418
  }
@@ -22,6 +22,7 @@ require "fastruby/method_extension"
22
22
  require "fastruby/logging"
23
23
  require "fastruby/getlocals"
24
24
  require "fastruby_load_path"
25
+ require "fastruby/inliner/inliner"
25
26
 
26
27
  require FastRuby.fastruby_load_path + "/../ext/fastruby_base/fastruby_base"
27
28
 
@@ -34,13 +35,23 @@ module FastRuby
34
35
  def initialize(method_name, owner)
35
36
  @method_name = method_name
36
37
  @owner = owner
38
+ @observers = Hash.new
39
+ end
40
+
41
+ def observe(key, &blk)
42
+ @observers[key] = blk
43
+ end
44
+
45
+ def tree_changed
46
+ @observers.values.each do |observer|
47
+ observer.call(self)
48
+ end
37
49
  end
38
50
 
39
51
  def build(signature, noreturn = false)
40
52
  return nil unless tree
41
-
42
- no_cache = false
43
53
 
54
+ no_cache = false
44
55
  mname = FastRuby.make_str_signature(@method_name, signature)
45
56
 
46
57
  if @owner.respond_to? :method_hash
@@ -51,16 +62,21 @@ module FastRuby
51
62
  end
52
63
  end
53
64
 
54
- FastRuby.logger.info "Building #{@owner}::#{@method_name} for signature #{signature.inspect}"
55
-
65
+ rebuild(signature, noreturn)
66
+ end
67
+
68
+ def rebuild(signature, noreturn = false)
69
+ no_cache = false
70
+ mname = FastRuby.make_str_signature(@method_name, signature)
56
71
 
57
72
  require "fastruby/translator/translator"
58
73
  require "rubygems"
59
74
  require "inline"
60
75
  require "fastruby/inline_extension"
61
76
 
77
+ inliner = FastRuby::Inliner.new
78
+
62
79
  context = FastRuby::Context.new
63
- context.locals = locals
64
80
  context.options = options
65
81
 
66
82
  args_tree = if tree[0] == :defn
@@ -91,88 +107,127 @@ module FastRuby
91
107
  end
92
108
 
93
109
  context.infer_self = signature[0]
94
- c_code = context.to_c_method(tree,signature)
110
+
111
+ inliner.infer_self = context.infer_self
112
+ inliner.infer_lvar_map = context.infer_lvar_map
95
113
 
96
- unless options[:main]
97
- context.define_method_at_init(@owner,@method_name, args_tree.size+1, signature)
114
+ inlined_tree = inliner.inline(tree)
115
+ context.locals = locals + inliner.extra_locals
116
+
117
+ inliner.extra_inferences.each do |local, itype|
118
+ context.infer_lvar_map[local] = itype
98
119
  end
120
+
121
+ inliner.inlined_methods.each do |inlined_method|
122
+ inlined_method.observe("#{@owner}##{@method_name}") do |imethod|
123
+ rebuild(signature, noreturn)
124
+ end
125
+ end
126
+
127
+ alt_options = options.dup
128
+ alt_options.delete(:self)
129
+ code_sha1 = FastRuby.cache.hash_snippet(inlined_tree.inspect, FastRuby::VERSION + signature.map(&:to_s).join('-') + alt_options.inspect)
130
+
131
+ paths = FastRuby.cache.retrieve(code_sha1)
99
132
 
100
- so_name = nil
101
-
102
- old_class_self = $class_self
103
- $class_self = @owner
104
133
  $last_obj_proc = nil
105
-
106
- begin
107
-
108
- unless $inline_extra_flags
109
- $inline_extra_flags = true
110
-
111
- ['CFLAGS','CXXFLAGS','OPTFLAGS','cflags','cxxflags','optflags'].each do |name|
112
- RbConfig::CONFIG[name].gsub!(/\-O\d/,"-O1") if RbConfig::CONFIG[name]
134
+ if paths.empty?
135
+ FastRuby.logger.info "Compiling #{@owner}::#{@method_name} for signature #{signature.inspect}"
136
+ c_code = context.to_c_method(inlined_tree,signature)
137
+
138
+ unless options[:main]
139
+ context.define_method_at_init(@method_name, args_tree.size+1, signature)
140
+ end
141
+
142
+ so_name = nil
143
+
144
+ old_class_self = $class_self
145
+ $class_self = @owner
146
+
147
+ begin
148
+
149
+ unless $inline_extra_flags
150
+ $inline_extra_flags = true
151
+
152
+ ['CFLAGS','CXXFLAGS','OPTFLAGS','cflags','cxxflags','optflags'].each do |name|
153
+ RbConfig::CONFIG[name].gsub!(/\-O\d/,"-O1") if RbConfig::CONFIG[name]
154
+ end
155
+
156
+ if RUBY_VERSION =~ /^1\.8/
157
+ RbConfig::CONFIG['CFLAGS'] << " -DRUBY_1_8 -Wno-clobbered"
158
+ elsif RUBY_VERSION =~ /^1\.9/
159
+ RbConfig::CONFIG['CFLAGS'] << " -DRUBY_1_9 -Wno-clobbered"
160
+ end
113
161
  end
114
162
 
115
- if RUBY_VERSION =~ /^1\.8/
116
- RbConfig::CONFIG['CFLAGS'] << " -DRUBY_1_8 -Wno-clobbered"
117
- elsif RUBY_VERSION =~ /^1\.9/
118
- RbConfig::CONFIG['CFLAGS'] << " -DRUBY_1_9 -Wno-clobbered"
163
+ @owner.class_eval do
164
+ inline :C do |builder|
165
+ builder.inc << context.extra_code
166
+ builder.init_extra = context.init_extra
167
+
168
+ def builder.generate_ext
169
+ ext = []
170
+
171
+ @inc.unshift "#include \"ruby.h\""
172
+
173
+ ext << @inc
174
+ ext << nil
175
+ ext << @src.join("\n\n")
176
+ ext << nil
177
+ ext << nil
178
+ ext << "#ifdef __cplusplus"
179
+ ext << "extern \"C\" {"
180
+ ext << "#endif"
181
+ ext << " void Init_#{module_name}() {"
182
+
183
+ ext << @init_extra.join("\n") unless @init_extra.empty?
184
+
185
+ ext << nil
186
+ ext << " }"
187
+ ext << "#ifdef __cplusplus"
188
+ ext << "}"
189
+ ext << "#endif"
190
+ ext << nil
191
+
192
+ ext.join "\n"
193
+ end
194
+
195
+ builder.c c_code
196
+ so_name = builder.so_name
197
+ end
119
198
  end
120
- end
121
199
 
122
- @owner.class_eval do
123
- inline :C do |builder|
124
- builder.inc << context.extra_code
125
- builder.init_extra = context.init_extra
126
-
127
- def builder.generate_ext
128
- ext = []
129
-
130
- @inc.unshift "#include \"ruby.h\""
131
-
132
- ext << @inc
133
- ext << nil
134
- ext << @src.join("\n\n")
135
- ext << nil
136
- ext << nil
137
- ext << "#ifdef __cplusplus"
138
- ext << "extern \"C\" {"
139
- ext << "#endif"
140
- ext << " void Init_#{module_name}() {"
141
-
142
- ext << @init_extra.join("\n") unless @init_extra.empty?
143
-
144
- ext << nil
145
- ext << " }"
146
- ext << "#ifdef __cplusplus"
147
- ext << "}"
148
- ext << "#endif"
149
- ext << nil
150
-
151
- ext.join "\n"
152
- end
153
-
154
- builder.c c_code
155
- so_name = builder.so_name
200
+ unless no_cache
201
+ no_cache = context.no_cache
156
202
  end
157
- end
158
-
159
- if $last_obj_proc
160
- unless options[:no_cache]
161
- FastRuby.cache.register_proc(so_name, $last_obj_proc)
203
+
204
+ unless no_cache
205
+ FastRuby.cache.insert(code_sha1, so_name)
162
206
  end
163
- $last_obj_proc.call($class_self)
207
+ ensure
208
+ $class_self = old_class_self
209
+ end
210
+ else
211
+ paths.each do |path|
212
+ require path
164
213
  end
214
+ end
165
215
 
216
+ if $last_obj_proc
217
+ FastRuby.cache.register_proc(code_sha1, $last_obj_proc)
218
+ end
219
+
220
+ $class_self = @owner
221
+ begin
222
+ FastRuby.cache.execute(code_sha1, signature, @owner)
166
223
  ensure
167
224
  $class_self = old_class_self
168
225
  end
169
-
170
- unless no_cache
171
- no_cache = context.no_cache
172
- end
173
-
174
- unless options[:no_cache]
175
- FastRuby.cache.insert(snippet_hash, so_name) unless no_cache
226
+
227
+ observe("#{@owner}##{@method_name}") do |imethod|
228
+ if tree
229
+ rebuild(signature, noreturn)
230
+ end
176
231
  end
177
232
  end
178
233
  end
@@ -194,10 +249,7 @@ module FastRuby
194
249
  end
195
250
 
196
251
  def method_added(method_name)
197
- if self.respond_to? :clear_method_hash_addresses
198
- FastRuby.unset_tree(self,method_name)
199
- self.clear_method_hash_addresses(method_hash(method_name))
200
- end
252
+ FastRuby.unset_tree(self,method_name)
201
253
  end
202
254
 
203
255
  def fastruby_method(mname_)