fastruby 0.0.18 → 0.0.19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. data/CHANGELOG +10 -0
  2. data/Rakefile +2 -1
  3. data/benchmarks/benchmark.rb~ +2 -4
  4. data/benchmarks/benchmark3.rb~ +2 -4
  5. data/ext/fastruby_base/fastruby_base.inl +1 -1
  6. data/lib/fastruby/builder.rb +8 -7
  7. data/lib/fastruby/fastruby_sexp.rb +18 -0
  8. data/lib/fastruby/inliner/modules/call.rb +254 -67
  9. data/lib/fastruby/inliner/modules/recursive.rb +5 -0
  10. data/lib/fastruby/reductor/modules/case.rb +2 -1
  11. data/lib/fastruby/translator/modules/block.rb +65 -59
  12. data/lib/fastruby/translator/modules/call.rb +7 -4
  13. data/lib/fastruby/translator/modules/exceptions.rb +66 -64
  14. data/lib/fastruby/translator/modules/flow.rb +8 -8
  15. data/lib/fastruby/translator/modules/literal.rb +5 -4
  16. data/lib/fastruby/translator/modules/method_group.rb +6 -5
  17. data/lib/fastruby/translator/modules/nonlocal.rb +153 -11
  18. data/lib/fastruby/translator/modules/static.rb +8 -8
  19. data/lib/fastruby/translator/modules/variable.rb +15 -15
  20. data/lib/fastruby/translator/translator.rb +156 -59
  21. data/lib/fastruby.rb +1 -1
  22. data/lib/fastruby.rb~ +36 -0
  23. data/spec/fastruby/inliner/modules/call_spec.rb +0 -0
  24. data/spec/fastruby/translator/modules/nonlocal_spec.rb +0 -0
  25. data/spec/fastruby/translator/translator_spec.rb +0 -0
  26. data/spec/ruby/base_spec.rb~ +5 -5
  27. data/spec/ruby/block/break_spec.rb~ +236 -0
  28. data/spec/ruby/block/lambda_spec.rb~ +38 -0
  29. data/spec/ruby/block/next_spec.rb~ +85 -0
  30. data/spec/ruby/call/base_call_spec.rb~ +83 -0
  31. data/spec/ruby/defn/replacement_spec.rb +52 -2
  32. data/spec/ruby/defn/replacement_spec.rb~ +52 -2
  33. data/spec/ruby/exception/base_spec.rb +22 -1
  34. data/spec/ruby/return_spec.rb~ +99 -0
  35. metadata +30 -10
@@ -42,55 +42,55 @@ module FastRuby
42
42
  }
43
43
 
44
44
  splat_arg = tree.find{|x| x == :yield ? false : x[0] == :splat}
45
- ret = nil
46
- if splat_arg
47
- ret = "
48
- VALUE splat_array = Qnil;
49
- VALUE block_aux = Qnil;
50
- #{to_c(splat_arg[1], "splat_array")};
51
-
52
- if (CLASS_OF(splat_array) == rb_cArray) {
53
- VALUE block_args[_RARRAY_LEN(splat_array) + #{tree.size}];
54
- int i;
55
- #{
56
- (0..tree.size-3).map{|i|
57
- "
58
- #{to_c(tree[i+1], "block_aux")};
59
- block_args[#{i}] = block_aux;
60
- "
61
- }.join(";\n")
62
- };
45
+
46
+ protected_block(false) do
47
+ if splat_arg
48
+ "
49
+ VALUE splat_array = Qnil;
50
+ VALUE block_aux = Qnil;
51
+ #{to_c(splat_arg[1], "splat_array")};
63
52
 
64
- for (i=0; i<_RARRAY_LEN(splat_array); i++) {
65
- block_args[i+#{tree.size-2}] = rb_ary_entry(splat_array,i);
53
+ if (CLASS_OF(splat_array) == rb_cArray) {
54
+ VALUE block_args[_RARRAY_LEN(splat_array) + #{tree.size}];
55
+ int i;
56
+ #{
57
+ (0..tree.size-3).map{|i|
58
+ "
59
+ #{to_c(tree[i+1], "block_aux")};
60
+ block_args[#{i}] = block_aux;
61
+ "
62
+ }.join(";\n")
63
+ };
64
+
65
+ for (i=0; i<_RARRAY_LEN(splat_array); i++) {
66
+ block_args[i+#{tree.size-2}] = rb_ary_entry(splat_array,i);
67
+ }
68
+
69
+ last_expression = #{anonymous_function(&block_code)}((VALUE)pframe, block_args, _RARRAY_LEN(splat_array) + #{tree.size-2});
70
+ } else {
71
+ VALUE block_args[1+#{tree.size}];
72
+ #{
73
+ (0..tree.size-3).map{|i|
74
+ "
75
+ #{to_c(tree[i+1], "block_aux")};
76
+ block_args[#{i}] = block_aux;
77
+ "
78
+ }.join(";\n")
79
+ };
80
+
81
+ block_args[#{tree.size-2}] = splat_array;
82
+ last_expression = #{anonymous_function(&block_code)}((VALUE)pframe, block_args, #{tree.size-1});
66
83
  }
67
84
 
68
- last_expression = #{anonymous_function(&block_code)}((VALUE)pframe, block_args, _RARRAY_LEN(splat_array) + #{tree.size-2});
69
- } else {
70
- VALUE block_args[1+#{tree.size}];
71
- #{
72
- (0..tree.size-3).map{|i|
73
- "
74
- #{to_c(tree[i+1], "block_aux")};
75
- block_args[#{i}] = block_aux;
76
- "
77
- }.join(";\n")
78
- };
79
-
80
- block_args[#{tree.size-2}] = splat_array;
81
- last_expression = #{anonymous_function(&block_code)}((VALUE)pframe, block_args, #{tree.size-1});
82
- }
83
-
84
- "
85
- else
86
- ret = if tree.size > 1
87
- "last_expression = " + anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){#{tree[1..-1].map{|subtree| to_c subtree}.join(",")}},#{tree.size-1})"
88
- else
89
- "last_expression = " + anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){}, #{tree.size-1})"
90
- end
85
+ "
86
+ else
87
+ if tree.size > 1
88
+ "last_expression = " + anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){#{tree[1..-1].map{|subtree| to_c subtree}.join(",")}},#{tree.size-1})"
89
+ else
90
+ "last_expression = " + anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){}, #{tree.size-1})"
91
+ end
92
+ end
91
93
  end
92
-
93
- protected_block(ret, false)
94
94
  end
95
95
 
96
96
  define_translator_for(:block, :method => :to_c_block)
@@ -98,24 +98,30 @@ module FastRuby
98
98
  if tree.size == 1
99
99
  return inline_block("return Qnil;")
100
100
  end
101
-
102
- str = ""
103
- str = tree[1..-2].map{ |subtree|
104
- to_c(subtree,"last_expression")
105
- }.join(";")
106
101
 
107
- if tree[-1]
108
- str = str + ";#{to_c(tree[-1],"last_expression")};"
109
- end
110
-
111
- if result_variable
112
- str << "#{result_variable} = last_expression;"
102
+ code = proc{
103
+
104
+ str = tree[1..-2].map{ |subtree|
105
+ to_c(subtree,"last_expression")
106
+ }.join(";")
107
+
108
+ if tree[-1]
109
+ str = str + ";#{to_c(tree[-1],"last_expression")};"
110
+ end
111
+
112
+ if result_variable
113
+ str << "#{result_variable} = last_expression;"
114
+ else
115
+ str << "return last_expression;"
116
+ end
113
117
  str
118
+ }
119
+
120
+ if result_variable
121
+ code.call
114
122
  else
115
- str << "return last_expression;"
116
- inline_block str
123
+ inline_block &code
117
124
  end
118
125
  end
119
-
120
126
  end
121
127
  end
@@ -170,7 +170,7 @@ module FastRuby
170
170
 
171
171
 
172
172
  if block_pass_arg or result_var
173
- code = "
173
+ code = proc{ "
174
174
  {
175
175
  VALUE recv = Qnil;
176
176
  #{to_c recv, "recv"};
@@ -213,8 +213,9 @@ module FastRuby
213
213
  }
214
214
  }
215
215
  "
216
+ }
216
217
 
217
- result_var ? code : inline_block(code)
218
+ result_var ? code.call : inline_block(&code)
218
219
  else
219
220
  "((VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(#{to_c recv}, Qfalse, (VALUE)pframe, 0, (VALUE[]){})"
220
221
  end
@@ -225,7 +226,7 @@ module FastRuby
225
226
 
226
227
  strargs = (0..args_tree.size-2).map{|i| "#{suffix}arg#{i}"}.join(",")
227
228
  if block_pass_arg or result_var
228
- code = "
229
+ code = proc{ "
229
230
  {
230
231
  VALUE recv = Qnil;
231
232
 
@@ -281,7 +282,9 @@ module FastRuby
281
282
 
282
283
  }
283
284
  "
284
- result_var ? code : inline_block(code)
285
+ }
286
+
287
+ result_var ? code.call : inline_block(&code)
285
288
  else
286
289
  strargs = args[1..-1].map{|arg| to_c arg}.join(",")
287
290
  "((VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(#{to_c recv}, Qfalse, (VALUE)pframe, #{args.size-1}, (VALUE[]){#{strargs}})"
@@ -23,73 +23,75 @@ module FastRuby
23
23
 
24
24
  define_translator_for(:rescue, :method => :to_c_rescue, :arity => 1)
25
25
  def to_c_rescue(tree)
26
- if tree[1][0] == :resbody
27
- else_tree = tree[2]
28
-
29
- if else_tree
30
- to_c else_tree
31
- else
32
- "Qnil"
33
- end
34
- else
35
- resbody_tree = tree[2]
36
- else_tree = nil
37
- if tree[-1]
38
- if tree[-1][0] != :resbody
39
- else_tree = tree[-1]
26
+ catch_on_throw do
27
+ if tree[1][0] == :resbody
28
+ else_tree = tree[2]
29
+
30
+ if else_tree
31
+ to_c else_tree
32
+ else
33
+ "Qnil"
40
34
  end
41
- end
42
-
43
- catch_condition_array = []
44
- lasgn_code = ""
45
- resbody_code = to_c(resbody_tree[2])
46
-
47
- rescue_code = ""
48
-
49
- tree[1..-1].each do |resbody_tree|
50
- next if resbody_tree[0] != :resbody
51
-
52
- if resbody_tree[1].size == 1
53
- resbody_tree[1][1] = s(:const, :Exception)
54
- end
55
-
56
- if resbody_tree[1].last[0] == :lasgn
57
- lasgn_code = to_c(resbody_tree[1].last)
35
+ else
36
+ resbody_tree = tree[2]
37
+ else_tree = nil
38
+ if tree[-1]
39
+ if tree[-1][0] != :resbody
40
+ else_tree = tree[-1]
41
+ end
58
42
  end
59
-
60
- resbody_tree[1][1..-1].each do |xtree|
61
- if xtree[0] != :lasgn
62
- trapcode = "rb_eException";
63
-
64
- if xtree
65
- trapcode = to_c(xtree)
43
+
44
+ catch_condition_array = []
45
+ lasgn_code = ""
46
+ resbody_code = to_c(resbody_tree[2])
47
+
48
+ rescue_code = ""
49
+
50
+ tree[1..-1].each do |resbody_tree|
51
+ next if resbody_tree[0] != :resbody
52
+
53
+ if resbody_tree[1].size == 1
54
+ resbody_tree[1][1] = s(:const, :Exception)
55
+ end
56
+
57
+ if resbody_tree[1].last[0] == :lasgn
58
+ lasgn_code = to_c(resbody_tree[1].last)
59
+ end
60
+
61
+ resbody_tree[1][1..-1].each do |xtree|
62
+ if xtree[0] != :lasgn
63
+ trapcode = "rb_eException";
64
+
65
+ if xtree
66
+ trapcode = to_c(xtree)
67
+ end
68
+
69
+ catch_condition_array << "(rb_obj_is_kind_of(frame.thread_data->exception,#{trapcode}) == Qtrue)"
66
70
  end
67
-
68
- catch_condition_array << "(rb_obj_is_kind_of(frame.thread_data->exception,#{trapcode}) == Qtrue)"
69
71
  end
70
- end
71
-
72
- rescue_code << "
73
- if (aux == FASTRUBY_TAG_RAISE) {
74
- if (#{catch_condition_array.join(" || ")})
75
- {
76
- // trap exception
77
- frame.targetted = 1;
78
-
79
- #{lasgn_code};
80
-
81
- #{resbody_code};
72
+
73
+ rescue_code << "
74
+ if (aux == FASTRUBY_TAG_RAISE) {
75
+ if (#{catch_condition_array.join(" || ")})
76
+ {
77
+ // trap exception
78
+ frame.targetted = 1;
79
+
80
+ #{lasgn_code};
81
+
82
+ #{resbody_code};
83
+ }
82
84
  }
83
- }
84
- "
85
+ "
86
+ end
87
+
88
+ frame_call(
89
+ "ret = " + frame(to_c(tree[1])+";","
90
+ #{rescue_code}
91
+ ", else_tree ? to_c(else_tree) : nil, 1)
92
+
93
+ )
85
94
  end
86
-
87
- frame_call(
88
- "ret = " + frame(to_c(tree[1])+";","
89
- #{rescue_code}
90
- ", else_tree ? to_c(else_tree) : nil, 1)
91
-
92
- )
93
95
  end
94
96
  end
95
97
 
@@ -99,9 +101,9 @@ module FastRuby
99
101
  to_c tree[1]
100
102
  else
101
103
  ensured_code = to_c tree[2]
102
- inline_block "
103
- #{frame(to_c(tree[1]),ensured_code,ensured_code,1)};
104
- "
104
+ inline_block {
105
+ "#{frame(to_c(tree[1]),ensured_code,ensured_code,1)};"
106
+ }
105
107
  end
106
108
  end
107
109
 
@@ -31,7 +31,7 @@ module FastRuby
31
31
  infered_value = infer_value(condition_tree)
32
32
  unless infered_value
33
33
 
34
- code = "
34
+ code = proc{"
35
35
  {
36
36
  VALUE condition_result;
37
37
  #{to_c condition_tree, "condition_result"};
@@ -44,12 +44,12 @@ module FastRuby
44
44
  " : ""
45
45
  }
46
46
  }
47
- "
47
+ "}
48
48
 
49
49
  if result_variable_
50
- code
50
+ code.call
51
51
  else
52
- inline_block code + "; return last_expression;"
52
+ inline_block { code.call + "; return last_expression;" }
53
53
  end
54
54
  else
55
55
  if infered_value.value
@@ -70,7 +70,7 @@ module FastRuby
70
70
  begin_while = "begin_while_"+rand(10000000).to_s
71
71
  end_while = "end_while_"+rand(10000000).to_s
72
72
  aux_varname = "_aux_" + rand(10000000).to_s
73
- code = "
73
+ code = proc{ "
74
74
  {
75
75
  VALUE while_condition;
76
76
  VALUE #{aux_varname};
@@ -90,12 +90,12 @@ module FastRuby
90
90
  end
91
91
  }
92
92
  }
93
- "
93
+ "}
94
94
 
95
95
  if result_var
96
- code
96
+ code.call
97
97
  else
98
- inline_block code
98
+ inline_block &code
99
99
  end
100
100
 
101
101
  end
@@ -32,6 +32,7 @@ module FastRuby
32
32
  key_tmp_var = "_key_"+rand(1000000).to_s
33
33
  value_tmp_var = "_value_"+rand(1000000).to_s
34
34
 
35
+ code = proc{
35
36
  hash_aset_code = ""
36
37
  (0..(tree.size-3)/2).each do |i|
37
38
  strkey = to_c tree[1 + i * 2]
@@ -49,7 +50,7 @@ module FastRuby
49
50
  "
50
51
  end
51
52
 
52
- code = "
53
+ "
53
54
  {
54
55
  VALUE #{hash_tmp_var} = rb_hash_new();
55
56
  #{hash_aset_code};
@@ -61,12 +62,12 @@ module FastRuby
61
62
  end
62
63
  };
63
64
  }
64
- "
65
+ "}
65
66
 
66
67
  if result_var
67
- code
68
+ code.call
68
69
  else
69
- inline_block code
70
+ inline_block &code
70
71
  end
71
72
  end
72
73
 
@@ -89,8 +89,8 @@ private
89
89
  alt_locals << local
90
90
  end
91
91
 
92
+ code = proc{
92
93
  fun = nil
93
-
94
94
  locals_scope(alt_locals) do
95
95
  fun = anonymous_function { |method_name| "static VALUE #{method_name}(VALUE self) {
96
96
 
@@ -158,8 +158,8 @@ private
158
158
  "
159
159
  }
160
160
  end
161
-
162
- code = "
161
+
162
+ "
163
163
  {
164
164
  #{init_code}
165
165
 
@@ -168,11 +168,12 @@ private
168
168
  #{fun}(tmpklass);
169
169
  }
170
170
  "
171
+ }
171
172
 
172
173
  if result_var
173
- code + "\n#{result_var} = Qnil;\n"
174
+ code.call + "\n#{result_var} = Qnil;\n"
174
175
  else
175
- inline_block code + "\nreturn Qnil;\n"
176
+ inline_block &code + "\nreturn Qnil;\n"
176
177
  end
177
178
 
178
179
  end
@@ -23,15 +23,16 @@ module FastRuby
23
23
 
24
24
  define_translator_for(:return, :method => :to_c_return)
25
25
  def to_c_return(tree, return_variable = nil)
26
- code = "
26
+ code = proc{"
27
27
  #{to_c(tree[1],"last_expression")};
28
28
  goto local_return;
29
29
  return Qnil;
30
- "
30
+ "}
31
+
31
32
  if return_variable
32
- code
33
+ code.call
33
34
  else
34
- inline_block code
35
+ inline_block &code
35
36
  end
36
37
  end
37
38
 
@@ -40,7 +41,7 @@ module FastRuby
40
41
 
41
42
  value_tmp_var = "value_" + rand(10000000).to_s
42
43
 
43
- code = "
44
+ code = proc{"
44
45
 
45
46
  {
46
47
  VALUE #{value_tmp_var} = Qnil;
@@ -65,10 +66,10 @@ module FastRuby
65
66
  longjmp(pframe->jmp,FASTRUBY_TAG_BREAK);
66
67
 
67
68
  }
68
- "
69
+ "}
69
70
 
70
71
  if result_var
71
- code
72
+ code.call
72
73
  else
73
74
  inline_block code
74
75
  end
@@ -117,7 +118,7 @@ module FastRuby
117
118
  def to_c_next(tree, result_var = nil)
118
119
  tmp_varname = "_acc_" + rand(10000000).to_s
119
120
  if @on_block
120
- code = "
121
+ code =proc {"
121
122
  {
122
123
  last_expression = Qnil;
123
124
 
@@ -129,15 +130,156 @@ module FastRuby
129
130
  pframe->thread_data->accumulator = last_expression;
130
131
  goto fastruby_local_next;
131
132
  }
132
- "
133
+ "}
134
+
133
135
  if result_var
134
- code
136
+ code.call
135
137
  else
136
- inline_block code
138
+ inline_block &code
137
139
  end
138
140
  else
139
141
  _raise("rb_eLocalJumpError","illegal next");
140
142
  end
141
143
  end
144
+
145
+ define_method_handler(:to_c, :priority => 100) { |tree, result_var = nil|
146
+
147
+ call_tree = tree[1]
148
+ catch_tag_id = call_tree[3][1][1]
149
+ included_catch_jmp = false
150
+
151
+ @catch_jmp = @catch_jmp || Set.new
152
+
153
+ begin
154
+ inner_code = catch_block(catch_tag_id) do
155
+ to_c(tree[3],result_var)
156
+ end
157
+
158
+ included_catch_jmp = true if @catch_jmp.include?(catch_tag_id)
159
+ ensure
160
+ @catch_jmp.delete(catch_tag_id)
161
+ end
162
+
163
+ if included_catch_jmp
164
+ new_frame = anonymous_function{ |name| "
165
+ static VALUE #{name}(VALUE param) {
166
+ volatile VALUE last_expression = Qnil;
167
+ #{@frame_struct} frame;
168
+
169
+ typeof(frame)* volatile pframe;
170
+ typeof(frame)* volatile parent_frame;
171
+ #{@locals_struct}* volatile plocals;
172
+
173
+ parent_frame = (void*)param;
174
+
175
+ frame.parent_frame = (void*)param;
176
+ frame.plocals = parent_frame->plocals;
177
+ frame.rescue = parent_frame->rescue;
178
+ frame.targetted = 0;
179
+ frame.thread_data = parent_frame->thread_data;
180
+ frame.return_value = Qnil;
181
+ frame.thread_data->accumulator = Qnil;
182
+ if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
183
+
184
+ plocals = frame.plocals;
185
+ pframe = &frame;
186
+
187
+ volatile int aux = setjmp(frame.jmp);
188
+ if (aux != 0) {
189
+ // restore previous frame
190
+ typeof(pframe) original_frame = pframe;
191
+ pframe = parent_frame;
192
+
193
+ if (aux == (int)#{intern_num catch_tag_id.to_s + "_end"}) {
194
+ return frame.thread_data->accumulator;
195
+ } else if (aux == (int)#{intern_num catch_tag_id.to_s + "_start"}) {
196
+ } else {
197
+ longjmp(pframe->jmp,aux);
198
+ }
199
+
200
+ return last_expression;
201
+ }
202
+
203
+ #{catch_tag_id.to_s}_start:
204
+ #{inner_code};
205
+ #{catch_tag_id.to_s}_end:
206
+ return last_expression;
207
+ #{@catch_blocks.map { |cb|
208
+ "#{cb.to_s}_end:
209
+
210
+ plocals->return_value = last_expression;
211
+ plocals->targetted = 1;
212
+ longjmp(pframe->jmp, #{intern_num( cb.to_s + "_end")});
213
+
214
+ #{cb.to_s}_start:
215
+
216
+ plocals->return_value = last_expression;
217
+ plocals->targetted = 1;
218
+ longjmp(pframe->jmp, #{intern_num( cb.to_s + "_start")});
219
+
220
+ "
221
+
222
+ }.join("\n")
223
+ }
224
+
225
+ }
226
+ "
227
+ } + "((VALUE)pframe)"
228
+
229
+ if result_var
230
+ "#{result_var} = #{new_frame};"
231
+ else
232
+ new_frame
233
+ end
234
+ else
235
+ "
236
+ #{catch_tag_id.to_s}_start:
237
+ #{inner_code};
238
+ #{catch_tag_id.to_s}_end:
239
+
240
+ "
241
+ end
242
+
243
+ }.condition{|tree, result_var = nil|
244
+ tree.node_type == :iter && tree[1][2] == :_catch
245
+ }
246
+
247
+ define_method_handler(:to_c, :priority => 100) { |tree, result_var = nil|
248
+ code = ""
249
+
250
+ catch_tag_id = tree[3][1][1]
251
+
252
+ if @catch_jmp_on_throw
253
+ @catch_jmp << catch_tag_id
254
+ end
255
+
256
+ code << to_c(tree[3][2] || fs(:nil), "last_expression")
257
+ code << "pframe->thread_data->accumulator = last_expression;"
258
+ code << "goto #{catch_tag_id.to_s}_end;"
259
+
260
+ if result_var
261
+ code
262
+ else
263
+ inline_block code
264
+ end
265
+ }.condition{|tree, result_var = nil|
266
+ tree.node_type == :call && tree[2] == :_throw
267
+ }
268
+
269
+ define_method_handler(:to_c, :priority => 100) { |tree, result_var = nil|
270
+ code = ""
271
+
272
+ catch_tag_id = tree[3][1][1]
273
+ code << "goto #{catch_tag_id.to_s}_start;"
274
+
275
+ if result_var
276
+ code
277
+ else
278
+ inline_block code
279
+ end
280
+ }.condition{|tree, result_var = nil|
281
+ tree.node_type == :call && tree[2] == :_loop
282
+ }
283
+
142
284
  end
143
285
  end