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
@@ -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_)