fastruby 0.0.16 → 0.0.17
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/CHANGELOG +17 -1
- data/Rakefile +1 -1
- data/ext/fastruby_base/fastruby_base.inl +81 -3
- data/lib/fastruby/fastruby_sexp.rb +21 -0
- data/lib/fastruby/getlocals.rb +2 -1
- data/lib/fastruby/object.rb +1 -1
- data/lib/fastruby/sexp_extension.rb +189 -0
- data/lib/fastruby/sexp_extension_edges.rb +210 -0
- data/lib/fastruby/translator/modules/block.rb +29 -22
- data/lib/fastruby/translator/modules/call.rb +211 -34
- data/lib/fastruby/translator/modules/defn.rb +64 -29
- data/lib/fastruby/translator/modules/exceptions.rb +1 -1
- data/lib/fastruby/translator/modules/flow.rb +93 -31
- data/lib/fastruby/translator/modules/iter.rb +277 -340
- data/lib/fastruby/translator/modules/literal.rb +97 -20
- data/lib/fastruby/translator/modules/logical.rb +40 -5
- data/lib/fastruby/translator/modules/method_group.rb +41 -19
- data/lib/fastruby/translator/modules/nonlocal.rb +74 -29
- data/lib/fastruby/translator/modules/variable.rb +151 -42
- data/lib/fastruby/translator/scope_mode_helper.rb +161 -0
- data/lib/fastruby/translator/translator.rb +389 -302
- data/lib/fastruby.rb +1 -1
- data/lib/fastruby.rb~ +36 -0
- data/spec/edges_helper.rb +91 -0
- data/spec/graph/base_spec.rb +35 -0
- data/spec/graph/path_spec.rb +48 -0
- data/spec/graph/vertex_spec.rb +58 -0
- data/spec/ruby/block/proc_as_block_spec.rb +214 -0
- data/spec/ruby/block/redo_spec.rb +133 -0
- data/spec/ruby/defn/single_function_spec.rb +50 -0
- data/spec/scope_mode/base_spec.rb +55 -0
- data/spec/scope_mode/block_spec.rb +105 -0
- data/spec/scope_mode/call_spec.rb +24 -0
- data/spec/scope_mode/exception_spec.rb +34 -0
- data/spec/scope_mode/flow_spec.rb +99 -0
- data/spec/scope_mode/optimization_spec.rb +130 -0
- data/spec/sexp2graph/base_spec.rb +36 -0
- data/spec/sexp2graph/exception_spec.rb +172 -0
- data/spec/sexp2graph/flow_spec.rb +67 -0
- data/spec/sexp2graph/logical_spec.rb +21 -0
- data/spec/sexp2graph/variable_spec.rb +26 -0
- metadata +110 -120
- data/lib/fastruby/self +0 -82
- data/lib/len +0 -280
- data/spec/block/proc_as_block_spec.rb +0 -111
- data/spec/block/redo_spec.rb +0 -67
- /data/spec/{base_spec.rb → ruby/base_spec.rb} +0 -0
- /data/spec/{block → ruby/block}/arguments_spec.rb +0 -0
- /data/spec/{block → ruby/block}/block_as_proc_spec.rb +0 -0
- /data/spec/{block → ruby/block}/break_spec.rb +0 -0
- /data/spec/{block → ruby/block}/callcc_spec.rb +0 -0
- /data/spec/{block → ruby/block}/lambda_spec.rb +0 -0
- /data/spec/{block → ruby/block}/next_spec.rb +0 -0
- /data/spec/{block → ruby/block}/proc_spec.rb +0 -0
- /data/spec/{block → ruby/block}/retry_spec.rb +0 -0
- /data/spec/{block_spec.rb → ruby/block_spec.rb} +0 -0
- /data/spec/{call → ruby/call}/base_call_spec.rb +0 -0
- /data/spec/{call → ruby/call}/multiple_args_spec.rb +0 -0
- /data/spec/{control_spec.rb → ruby/control_spec.rb} +0 -0
- /data/spec/{defn → ruby/defn}/default_args_spec.rb +0 -0
- /data/spec/{defn → ruby/defn}/multiple_args_spec.rb +0 -0
- /data/spec/{defn → ruby/defn}/replacement_spec.rb +0 -0
- /data/spec/{exception → ruby/exception}/base_spec.rb +0 -0
- /data/spec/{exception → ruby/exception}/ensure_spec.rb +0 -0
- /data/spec/{exception → ruby/exception}/exc_trap_spec.rb +0 -0
- /data/spec/{exception → ruby/exception}/internal_ex_spec.rb +0 -0
- /data/spec/{exception → ruby/exception}/syntaxis_spec.rb +0 -0
- /data/spec/{expression_spec.rb → ruby/expression_spec.rb} +0 -0
- /data/spec/{flow_control → ruby/flow_control}/case_spec.rb +0 -0
- /data/spec/{flow_control → ruby/flow_control}/for_spec.rb +0 -0
- /data/spec/{integrity_spec.rb → ruby/integrity_spec.rb} +0 -0
- /data/spec/{jump → ruby/jump}/next_spec.rb +0 -0
- /data/spec/{literal_spec.rb → ruby/literal_spec.rb} +0 -0
- /data/spec/{module_spec.rb → ruby/module_spec.rb} +0 -0
- /data/spec/{return_spec.rb → ruby/return_spec.rb} +0 -0
- /data/spec/{singleton_spec.rb → ruby/singleton_spec.rb} +0 -0
- /data/spec/{sugar_spec.rb → ruby/sugar_spec.rb} +0 -0
- /data/spec/{variable_spec.rb → ruby/variable_spec.rb} +0 -0
@@ -23,7 +23,7 @@ module FastRuby
|
|
23
23
|
|
24
24
|
register_translator_module IterTranslator
|
25
25
|
|
26
|
-
def to_c_iter(tree)
|
26
|
+
def to_c_iter(tree, result_var = nil)
|
27
27
|
|
28
28
|
call_tree = tree[1]
|
29
29
|
args_tree = tree[2]
|
@@ -31,7 +31,11 @@ module FastRuby
|
|
31
31
|
|
32
32
|
directive_code = directive(call_tree)
|
33
33
|
if directive_code
|
34
|
-
|
34
|
+
if result_var
|
35
|
+
return "#{result_var} = #{directive_code};\n"
|
36
|
+
else
|
37
|
+
return directive_code
|
38
|
+
end
|
35
39
|
end
|
36
40
|
|
37
41
|
other_call_tree = call_tree.dup
|
@@ -75,31 +79,9 @@ module FastRuby
|
|
75
79
|
str_arg_initialization = ""
|
76
80
|
|
77
81
|
str_impl = ""
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
if anonymous_impl
|
82
|
-
if anonymous_impl[0] == :block
|
83
|
-
str_impl = anonymous_impl[1..-2].map{ |subtree|
|
84
|
-
to_c(subtree)
|
85
|
-
}.join(";")
|
86
|
-
|
87
|
-
if anonymous_impl[-1][0] != :return and anonymous_impl[-1][0] != :break and anonymous_impl[-1][0] != :next
|
88
|
-
str_impl = str_impl + ";last_expression = (#{to_c(anonymous_impl[-1])});"
|
89
|
-
else
|
90
|
-
str_impl = str_impl + ";#{to_c(anonymous_impl[-1])};"
|
91
|
-
end
|
92
|
-
else
|
93
|
-
if anonymous_impl[0] != :return and anonymous_impl[0] != :break and anonymous_impl[0] != :next
|
94
|
-
str_impl = str_impl + ";last_expression = (#{to_c(anonymous_impl)});"
|
95
|
-
else
|
96
|
-
str_impl = str_impl + ";#{to_c(anonymous_impl)};"
|
97
|
-
end
|
98
|
-
end
|
99
|
-
else
|
100
|
-
str_impl = "last_expression = Qnil;"
|
101
|
-
end
|
102
|
-
end
|
82
|
+
on_block do
|
83
|
+
str_impl = to_c(anonymous_impl, "last_expression")
|
84
|
+
end
|
103
85
|
|
104
86
|
if not args_tree
|
105
87
|
elsif args_tree.first == :lasgn
|
@@ -154,21 +136,70 @@ module FastRuby
|
|
154
136
|
end
|
155
137
|
end
|
156
138
|
end
|
157
|
-
|
139
|
+
str_recv = "pframe->next_recv"
|
140
|
+
str_recv = "plocals->self" unless recv_tree
|
158
141
|
|
159
|
-
|
142
|
+
strargs = if call_args_tree.size > 1
|
143
|
+
"," + (0..call_args_tree.size-2).map{|i| "arg#{i}"}.join(",")
|
144
|
+
else
|
145
|
+
""
|
146
|
+
end
|
147
|
+
|
148
|
+
str_evaluate_args = ""
|
160
149
|
|
161
|
-
|
150
|
+
rb_funcall_caller_code = proc { |name, call_type| "
|
151
|
+
static VALUE #{name}(VALUE param) {
|
152
|
+
// call to #{call_tree[2]}
|
153
|
+
VALUE last_expression = Qnil;
|
154
|
+
|
155
|
+
#{str_lvar_initialization}
|
156
|
+
#{str_evaluate_args};
|
157
|
+
|
158
|
+
VALUE ret = rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, #{call_args_tree.size-1} #{strargs});
|
159
|
+
#{
|
160
|
+
if call_type == :lambda
|
161
|
+
"
|
162
162
|
|
163
|
-
|
163
|
+
// freeze all stacks
|
164
|
+
struct FASTRUBYTHREADDATA* thread_data = rb_current_thread_data();
|
165
|
+
|
166
|
+
if (thread_data != 0) {
|
167
|
+
VALUE rb_stack_chunk = thread_data->rb_stack_chunk;
|
168
|
+
|
169
|
+
// add reference to stack chunk to lambda object
|
170
|
+
rb_ivar_set(ret,#{intern_num :_fastruby_stack_chunk},rb_stack_chunk);
|
171
|
+
|
172
|
+
// freeze the complete chain of stack chunks
|
173
|
+
while (rb_stack_chunk != Qnil) {
|
174
|
+
struct STACKCHUNK* stack_chunk;
|
175
|
+
Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
|
176
|
+
|
177
|
+
stack_chunk_freeze(stack_chunk);
|
178
|
+
|
179
|
+
rb_stack_chunk = rb_ivar_get(rb_stack_chunk,#{intern_num :_parent_stack_chunk});
|
180
|
+
}
|
181
|
+
}
|
182
|
+
"
|
183
|
+
end
|
184
|
+
}
|
185
|
+
return ret;
|
186
|
+
}
|
187
|
+
"
|
188
|
+
}
|
189
|
+
|
190
|
+
|
191
|
+
if call_args_tree.size > 1
|
164
192
|
if call_args_tree.last[0] == :splat
|
165
|
-
rb_funcall_caller_code = proc { |name| "
|
193
|
+
rb_funcall_caller_code = proc { |name,call_type| "
|
166
194
|
static VALUE #{name}(VALUE param) {
|
167
195
|
// call to #{call_tree[2]}
|
168
196
|
|
197
|
+
VALUE last_expression = Qnil;
|
169
198
|
#{str_lvar_initialization}
|
170
199
|
|
171
|
-
VALUE array =
|
200
|
+
VALUE array = Qnil;
|
201
|
+
|
202
|
+
#{to_c call_args_tree.last[1], "array"};
|
172
203
|
|
173
204
|
if (TYPE(array) != T_ARRAY) {
|
174
205
|
array = rb_ary_new4(1,&array);
|
@@ -177,11 +208,15 @@ module FastRuby
|
|
177
208
|
int argc = #{call_args_tree.size-2};
|
178
209
|
VALUE argv[#{call_args_tree.size} + _RARRAY_LEN(array)];
|
179
210
|
|
211
|
+
VALUE aux_ = Qnil;;
|
180
212
|
#{
|
181
213
|
i = -1
|
182
214
|
call_args_tree[1..-2].map {|arg|
|
183
215
|
i = i + 1
|
184
|
-
"
|
216
|
+
"
|
217
|
+
#{to_c arg, "aux_"};
|
218
|
+
argv[#{i}] = aux_;
|
219
|
+
"
|
185
220
|
}.join(";\n")
|
186
221
|
};
|
187
222
|
|
@@ -196,67 +231,24 @@ module FastRuby
|
|
196
231
|
return rb_funcall2(#{str_recv}, #{intern_num call_tree[2]}, argc, argv);
|
197
232
|
}
|
198
233
|
"
|
199
|
-
}
|
234
|
+
}
|
200
235
|
else
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
236
|
+
str_evaluate_args = "
|
237
|
+
#{
|
238
|
+
(0..call_args_tree.size-2).map{|i|
|
239
|
+
"VALUE arg#{i} = Qnil;"
|
240
|
+
}.join("\n")
|
241
|
+
}
|
242
|
+
|
243
|
+
#{
|
244
|
+
(0..call_args_tree.size-2).map{|i|
|
245
|
+
to_c(call_args_tree[i+1], "arg#{i}")+";"
|
246
|
+
}.join("\n")
|
247
|
+
}
|
209
248
|
"
|
210
|
-
}
|
211
249
|
end
|
212
|
-
|
213
|
-
rb_funcall_caller_code_with_lambda = rb_funcall_caller_code
|
214
|
-
else
|
215
|
-
str_recv = "pframe->next_recv"
|
216
|
-
str_recv = "plocals->self" unless recv_tree
|
217
|
-
|
218
|
-
rb_funcall_caller_code = proc { |name| "
|
219
|
-
static VALUE #{name}(VALUE param) {
|
220
|
-
// call to #{call_tree[2]}
|
221
|
-
#{str_lvar_initialization}
|
222
|
-
return rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, 0);
|
223
|
-
}
|
224
|
-
"
|
225
|
-
}
|
226
|
-
|
227
|
-
rb_funcall_caller_code_with_lambda = proc { |name| "
|
228
|
-
static VALUE #{name}(VALUE param) {
|
229
|
-
// call to #{call_tree[2]}
|
230
|
-
#{str_lvar_initialization}
|
231
|
-
VALUE ret = rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, 0);
|
232
|
-
|
233
|
-
// freeze all stacks
|
234
|
-
struct FASTRUBYTHREADDATA* thread_data = rb_current_thread_data();
|
235
|
-
|
236
|
-
if (thread_data != 0) {
|
237
|
-
VALUE rb_stack_chunk = thread_data->rb_stack_chunk;
|
238
|
-
|
239
|
-
// add reference to stack chunk to lambda object
|
240
|
-
rb_ivar_set(ret,#{intern_num :_fastruby_stack_chunk},rb_stack_chunk);
|
241
|
-
|
242
|
-
// freeze the complete chain of stack chunks
|
243
|
-
while (rb_stack_chunk != Qnil) {
|
244
|
-
struct STACKCHUNK* stack_chunk;
|
245
|
-
Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
|
246
|
-
|
247
|
-
stack_chunk_freeze(stack_chunk);
|
248
|
-
|
249
|
-
rb_stack_chunk = rb_ivar_get(rb_stack_chunk,#{intern_num :_parent_stack_chunk});
|
250
|
-
}
|
251
|
-
}
|
252
|
-
|
253
|
-
return ret;
|
254
|
-
}
|
255
|
-
"
|
256
|
-
}
|
250
|
+
end
|
257
251
|
|
258
|
-
end
|
259
|
-
|
260
252
|
argument_array_read = "
|
261
253
|
VALUE arg;
|
262
254
|
#{
|
@@ -279,17 +271,16 @@ module FastRuby
|
|
279
271
|
}
|
280
272
|
"
|
281
273
|
|
282
|
-
|
283
|
-
rb_funcall_block_code_with_lambda = proc { |name| "
|
274
|
+
rb_funcall_block_code = proc { |name,call_type| "
|
284
275
|
static VALUE #{name}(VALUE arg_, VALUE _plocals, int argc, VALUE* argv) {
|
285
276
|
// block for call to #{call_tree[2]}
|
286
277
|
#{argument_array_read}
|
287
|
-
|
288
|
-
VALUE last_expression = Qnil;
|
278
|
+
|
279
|
+
volatile VALUE last_expression = Qnil;
|
289
280
|
|
290
281
|
#{@frame_struct} frame;
|
291
|
-
#{@frame_struct} *pframe = (void*)&frame;
|
292
|
-
#{@locals_struct} *plocals = (void*)_plocals;
|
282
|
+
#{@frame_struct} * volatile pframe = (void*)&frame;
|
283
|
+
#{@locals_struct} * volatile plocals = (void*)_plocals;
|
293
284
|
|
294
285
|
frame.plocals = plocals;
|
295
286
|
frame.parent_frame = 0;
|
@@ -298,80 +289,50 @@ module FastRuby
|
|
298
289
|
frame.targetted = 0;
|
299
290
|
frame.thread_data = rb_current_thread_data();
|
300
291
|
|
301
|
-
|
302
|
-
VALUE old_call_frame = ((typeof(plocals))(pframe->plocals))->call_frame;
|
303
|
-
((typeof(plocals))(pframe->plocals))->call_frame = LONG2FIX(pframe);
|
292
|
+
#{str_arg_initialization}
|
304
293
|
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
294
|
+
#{
|
295
|
+
if call_type == :lambda or call_type == :proc_new
|
296
|
+
"
|
297
|
+
void* volatile old_call_frame = ((typeof(plocals))(pframe->plocals))->call_frame;
|
298
|
+
((typeof(plocals))(pframe->plocals))->call_frame = pframe;
|
299
|
+
"
|
300
|
+
end
|
301
|
+
}
|
302
|
+
|
303
|
+
int aux = setjmp(frame.jmp);
|
304
|
+
if (aux != 0) {
|
305
|
+
|
306
|
+
if (aux == FASTRUBY_TAG_NEXT) {
|
307
|
+
last_expression = pframe->thread_data->accumulator;
|
308
|
+
goto fastruby_local_next;
|
311
309
|
} else if (aux == FASTRUBY_TAG_REDO) {
|
312
310
|
// do nothing and let execute the block again
|
311
|
+
#{
|
312
|
+
if call_type == :lambda
|
313
|
+
"
|
314
|
+
|
315
|
+
} else if (aux == FASTRUBY_TAG_BREAK) {
|
316
|
+
last_expression = frame.return_value;
|
317
|
+
goto fastruby_local_next;
|
318
|
+
"
|
319
|
+
end
|
320
|
+
}
|
321
|
+
#{
|
322
|
+
if call_type == :lambda or call_type == :proc_new
|
323
|
+
"
|
313
324
|
} else if (aux == FASTRUBY_TAG_RAISE) {
|
314
325
|
rb_funcall(((typeof(plocals))(pframe->plocals))->self, #{intern_num :raise}, 1, frame.thread_data->exception);
|
315
326
|
return Qnil;
|
327
|
+
"
|
328
|
+
end
|
329
|
+
}
|
316
330
|
} else {
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
rb_raise(rb_eLocalJumpError, \"unexpected return\");
|
323
|
-
}
|
324
|
-
} else {
|
325
|
-
rb_raise(rb_eLocalJumpError, \"unexpected return\");
|
326
|
-
}
|
327
|
-
|
328
|
-
((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
|
329
|
-
return frame.return_value;
|
330
|
-
|
331
|
-
}
|
332
|
-
}
|
333
|
-
|
334
|
-
#{str_arg_initialization}
|
335
|
-
#{str_impl}
|
336
|
-
|
337
|
-
((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
|
338
|
-
return last_expression;
|
339
|
-
}
|
340
|
-
"
|
341
|
-
}
|
342
|
-
|
343
|
-
rb_funcall_block_code_proc_new = proc { |name| "
|
344
|
-
static VALUE #{name}(VALUE arg_, VALUE _plocals, int argc, VALUE* argv) {
|
345
|
-
// block for call to #{call_tree[2]}
|
346
|
-
#{argument_array_read}
|
347
|
-
|
348
|
-
VALUE last_expression = Qnil;
|
349
|
-
|
350
|
-
#{@frame_struct} frame;
|
351
|
-
#{@frame_struct} *pframe = (void*)&frame;
|
352
|
-
#{@locals_struct} *plocals = (void*)_plocals;
|
353
|
-
|
354
|
-
frame.plocals = plocals;
|
355
|
-
frame.parent_frame = 0;
|
356
|
-
frame.return_value = Qnil;
|
357
|
-
frame.rescue = 0;
|
358
|
-
frame.targetted = 0;
|
359
|
-
frame.thread_data = rb_current_thread_data();
|
360
|
-
|
361
|
-
// create a fake parent frame representing the lambda method frame and a fake locals scope
|
362
|
-
VALUE old_call_frame = ((typeof(plocals))(pframe->plocals))->call_frame;
|
363
|
-
((typeof(plocals))(pframe->plocals))->call_frame = LONG2FIX(pframe);
|
364
|
-
|
365
|
-
int aux = setjmp(frame.jmp);
|
366
|
-
if (aux != 0) {
|
367
|
-
if (aux == FASTRUBY_TAG_NEXT) {
|
368
|
-
return pframe->thread_data->accumulator;
|
369
|
-
} else if (aux == FASTRUBY_TAG_REDO) {
|
370
|
-
// do nothing and let execute the block again
|
371
|
-
} else if (aux == FASTRUBY_TAG_RAISE) {
|
372
|
-
rb_funcall(((typeof(plocals))(pframe->plocals))->self, #{intern_num :raise}, 1, frame.thread_data->exception);
|
373
|
-
return Qnil;
|
374
|
-
} else {
|
331
|
+
#{
|
332
|
+
case call_type
|
333
|
+
when :proc_new
|
334
|
+
"
|
335
|
+
_local_return:
|
375
336
|
if (plocals->targetted == 1) {
|
376
337
|
if (plocals->active == Qfalse) {
|
377
338
|
rb_raise(rb_eLocalJumpError,\"return from proc-closure\");
|
@@ -382,110 +343,86 @@ module FastRuby
|
|
382
343
|
} else {
|
383
344
|
rb_raise(rb_eLocalJumpError, \"unexpected return\");
|
384
345
|
}
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
return last_expression;
|
394
|
-
}
|
395
|
-
"
|
396
|
-
}
|
397
|
-
|
398
|
-
|
399
|
-
rb_funcall_block_code = proc { |name| "
|
400
|
-
static VALUE #{name}(VALUE arg_, VALUE _plocals, int argc, VALUE* argv) {
|
401
|
-
// block for call to #{call_tree[2]}
|
402
|
-
#{argument_array_read}
|
403
|
-
|
404
|
-
VALUE last_expression = Qnil;
|
405
|
-
|
406
|
-
#{@frame_struct} frame;
|
407
|
-
#{@frame_struct} *pframe = (void*)&frame;
|
408
|
-
#{@locals_struct} *plocals = (void*)_plocals;
|
409
|
-
|
410
|
-
frame.plocals = plocals;
|
411
|
-
frame.parent_frame = 0;
|
412
|
-
frame.return_value = Qnil;
|
413
|
-
frame.rescue = 0;
|
414
|
-
frame.targetted = 0;
|
415
|
-
frame.thread_data = rb_current_thread_data();
|
416
|
-
|
417
|
-
int aux = setjmp(frame.jmp);
|
418
|
-
if (aux != 0) {
|
346
|
+
"
|
347
|
+
when :lambda
|
348
|
+
"
|
349
|
+
if (aux == FASTRUBY_TAG_RETURN) {
|
350
|
+
if (plocals->targetted == 1) {
|
351
|
+
last_expression = ((typeof(plocals))(pframe->plocals))->return_value;
|
352
|
+
goto fastruby_local_next;
|
419
353
|
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
354
|
+
} else {
|
355
|
+
rb_raise(rb_eLocalJumpError, \"unexpected return\");
|
356
|
+
}
|
357
|
+
} else {
|
358
|
+
rb_raise(rb_eLocalJumpError, \"unexpected return\");
|
359
|
+
}
|
360
|
+
"
|
361
|
+
else
|
362
|
+
"
|
425
363
|
frb_jump_tag(aux);
|
426
364
|
return frame.return_value;
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
#{str_arg_initialization}
|
432
|
-
#{str_impl}
|
433
|
-
|
434
|
-
return last_expression;
|
435
|
-
}
|
436
|
-
"
|
437
|
-
}
|
438
|
-
|
439
|
-
rb_funcall_block_code_callcc = proc { |name| "
|
440
|
-
static VALUE #{name}(VALUE arg, VALUE _plocals, int argc, VALUE* argv) {
|
441
|
-
#{
|
442
|
-
# TODO: access directly to argc and argv for optimal execution
|
443
|
-
if RUBY_VERSION =~ /^1\.9/
|
444
|
-
"arg = rb_ary_new4(argc,argv);"
|
445
|
-
end
|
446
|
-
}
|
447
|
-
|
448
|
-
// block for call to #{call_tree[2]}
|
449
|
-
VALUE last_expression = Qnil;
|
450
|
-
|
451
|
-
#{@frame_struct} frame;
|
452
|
-
#{@frame_struct} *pframe = (void*)&frame;
|
453
|
-
#{@locals_struct} *plocals = (void*)_plocals;
|
454
|
-
|
455
|
-
frame.plocals = plocals;
|
456
|
-
frame.parent_frame = 0;
|
457
|
-
frame.return_value = Qnil;
|
458
|
-
frame.rescue = 0;
|
459
|
-
frame.targetted = 0;
|
460
|
-
frame.thread_data = rb_current_thread_data();
|
461
|
-
|
462
|
-
int aux = setjmp(frame.jmp);
|
463
|
-
if (aux != 0) {
|
365
|
+
"
|
366
|
+
end
|
367
|
+
}
|
464
368
|
|
465
|
-
if (aux == FASTRUBY_TAG_NEXT) {
|
466
|
-
return pframe->thread_data->accumulator;
|
467
|
-
} else if (aux == FASTRUBY_TAG_REDO) {
|
468
|
-
// do nothing and let execute the block again
|
469
|
-
} else {
|
470
|
-
frb_jump_tag(aux);
|
471
|
-
return frame.return_value;
|
472
369
|
}
|
473
370
|
}
|
474
|
-
|
371
|
+
|
372
|
+
#{
|
373
|
+
if call_type == :callcc
|
374
|
+
"
|
475
375
|
if (rb_obj_is_kind_of(arg, rb_const_get(rb_cObject, #{intern_num :Continuation}))) {
|
476
376
|
struct FASTRUBYTHREADDATA* thread_data = frame.thread_data;
|
477
377
|
rb_ivar_set(arg,#{intern_num :__stack_chunk},thread_data->rb_stack_chunk);
|
478
378
|
}
|
379
|
+
"
|
380
|
+
end
|
381
|
+
}
|
479
382
|
|
480
|
-
|
481
|
-
#{str_impl}
|
383
|
+
fastruby_local_redo:
|
384
|
+
#{str_impl};
|
482
385
|
|
386
|
+
#{
|
387
|
+
case call_type
|
388
|
+
when :proc_new
|
389
|
+
"
|
483
390
|
return last_expression;
|
484
|
-
|
391
|
+
local_return:
|
392
|
+
aux = FASTRUBY_TAG_RETURN;
|
393
|
+
plocals->return_value = last_expression;
|
394
|
+
plocals->targetted = 1;
|
395
|
+
goto _local_return;
|
396
|
+
"
|
397
|
+
when :lambda
|
398
|
+
"
|
399
|
+
local_return:
|
400
|
+
"
|
401
|
+
else
|
402
|
+
"
|
403
|
+
return last_expression;
|
404
|
+
local_return:
|
405
|
+
plocals->return_value = last_expression;
|
406
|
+
plocals->targetted = 1;
|
407
|
+
frb_jump_tag(FASTRUBY_TAG_RETURN);
|
408
|
+
"
|
409
|
+
end
|
410
|
+
}
|
411
|
+
|
412
|
+
|
413
|
+
fastruby_local_next:
|
414
|
+
#{
|
415
|
+
if call_type == :proc_new or call_type == :lambda
|
416
|
+
"
|
417
|
+
((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
|
418
|
+
"
|
419
|
+
end
|
420
|
+
}
|
421
|
+
return last_expression;
|
422
|
+
}
|
485
423
|
"
|
486
424
|
}
|
487
425
|
|
488
|
-
|
489
426
|
fastruby_str_arg_initialization = ""
|
490
427
|
|
491
428
|
if not args_tree
|
@@ -515,11 +452,11 @@ module FastRuby
|
|
515
452
|
block_code = proc { |name| "
|
516
453
|
static VALUE #{name}(int argc, VALUE* argv, VALUE _locals, VALUE _parent_frame) {
|
517
454
|
// block for call to #{call_tree[2]}
|
518
|
-
VALUE last_expression = Qnil;
|
455
|
+
volatile VALUE last_expression = Qnil;
|
519
456
|
#{@frame_struct} frame;
|
520
|
-
#{@frame_struct} *pframe = (void*)&frame;
|
521
|
-
#{@frame_struct} *parent_frame = (void*)_parent_frame;
|
522
|
-
#{@locals_struct} *plocals;
|
457
|
+
#{@frame_struct} * volatile pframe = (void*)&frame;
|
458
|
+
#{@frame_struct} * volatile parent_frame = (void*)_parent_frame;
|
459
|
+
#{@locals_struct} * volatile plocals;
|
523
460
|
|
524
461
|
frame.plocals = (void*)_locals;
|
525
462
|
frame.parent_frame = parent_frame;
|
@@ -531,6 +468,8 @@ module FastRuby
|
|
531
468
|
|
532
469
|
plocals = frame.plocals;
|
533
470
|
|
471
|
+
#{fastruby_str_arg_initialization}
|
472
|
+
|
534
473
|
int aux = setjmp(frame.jmp);
|
535
474
|
if (aux != 0) {
|
536
475
|
if (pframe->targetted == 0) {
|
@@ -545,63 +484,35 @@ module FastRuby
|
|
545
484
|
|
546
485
|
}
|
547
486
|
|
548
|
-
|
549
|
-
#{str_impl}
|
487
|
+
fastruby_local_redo:
|
488
|
+
#{str_impl};
|
550
489
|
|
551
490
|
return last_expression;
|
552
|
-
|
491
|
+
local_return:
|
492
|
+
plocals->return_value = last_expression;
|
493
|
+
plocals->targetted = 1;
|
494
|
+
longjmp(pframe->jmp, FASTRUBY_TAG_RETURN);
|
495
|
+
fastruby_local_next:
|
496
|
+
return last_expression; }
|
553
497
|
"
|
554
498
|
}
|
555
499
|
|
556
|
-
str_recv = "plocals->self"
|
557
|
-
|
558
|
-
if recv_tree
|
559
|
-
str_recv = to_c recv_tree
|
560
|
-
end
|
561
|
-
|
562
500
|
caller_code = nil
|
563
501
|
convention_global_name = add_global_name("int",0)
|
564
|
-
|
565
|
-
call_frame_struct_code = "
|
566
|
-
#{@block_struct} block;
|
567
|
-
|
568
|
-
block.block_function_address = (void*)#{anonymous_function(&block_code)};
|
569
|
-
block.block_function_param = (void*)plocals;
|
570
|
-
|
571
|
-
// create a call_frame
|
572
|
-
#{@frame_struct} call_frame;
|
573
|
-
|
574
|
-
call_frame.parent_frame = (void*)pframe;
|
575
|
-
call_frame.plocals = plocals;
|
576
|
-
call_frame.return_value = Qnil;
|
577
|
-
call_frame.targetted = 0;
|
578
|
-
call_frame.thread_data = rb_current_thread_data();
|
579
|
-
|
580
|
-
VALUE old_call_frame = plocals->call_frame;
|
581
|
-
plocals->call_frame = LONG2FIX(&call_frame);
|
582
|
-
|
583
|
-
int aux = setjmp(call_frame.jmp);
|
584
|
-
if (aux != 0) {
|
585
|
-
#{@frame_struct}* pframe_ = (void*)pframe;
|
586
|
-
|
587
|
-
if (aux == FASTRUBY_TAG_RETRY ) {
|
588
|
-
// do nothing and let the call execute again
|
589
|
-
} else {
|
590
|
-
if (call_frame.targetted == 0) {
|
591
|
-
longjmp(pframe_->jmp,aux);
|
592
|
-
}
|
593
|
-
|
594
|
-
plocals->call_frame = old_call_frame;
|
595
|
-
return call_frame.return_value;
|
596
|
-
}
|
597
|
-
}
|
598
|
-
"
|
599
502
|
|
600
503
|
precode = "
|
601
504
|
struct FASTRUBYTHREADDATA* thread_data = 0;
|
602
|
-
VALUE saved_rb_stack_chunk = Qnil;
|
505
|
+
VALUE saved_rb_stack_chunk = Qnil;
|
506
|
+
|
507
|
+
VALUE next_recv = plocals->self;
|
508
|
+
|
509
|
+
#{
|
510
|
+
if recv_tree
|
511
|
+
to_c recv_tree, "next_recv"
|
512
|
+
end
|
513
|
+
};
|
603
514
|
|
604
|
-
pframe->next_recv =
|
515
|
+
pframe->next_recv = next_recv;
|
605
516
|
#ifdef RUBY_1_8
|
606
517
|
NODE* node = rb_method_node(CLASS_OF(pframe->next_recv), #{intern_num mname});
|
607
518
|
#endif
|
@@ -639,9 +550,9 @@ module FastRuby
|
|
639
550
|
|
640
551
|
|
641
552
|
funcall_call_code = "
|
642
|
-
|
553
|
+
#{
|
643
554
|
frame_call(
|
644
|
-
protected_block(
|
555
|
+
"ret = " + protected_block("
|
645
556
|
|
646
557
|
void* caller_func;
|
647
558
|
void* block_func;
|
@@ -662,21 +573,21 @@ module FastRuby
|
|
662
573
|
node == #{@lambda_node_gvar}
|
663
574
|
) {
|
664
575
|
|
665
|
-
caller_func = #{anonymous_function(
|
666
|
-
block_func = #{anonymous_function(
|
576
|
+
caller_func = #{anonymous_function(:lambda,&rb_funcall_caller_code)};
|
577
|
+
block_func = #{anonymous_function(:lambda,&rb_funcall_block_code)};
|
667
578
|
} else if (node == #{@procnew_node_gvar} && pframe->next_recv == rb_cProc) {
|
668
|
-
caller_func = #{anonymous_function(
|
669
|
-
block_func = #{anonymous_function(
|
579
|
+
caller_func = #{anonymous_function(:lambda,&rb_funcall_caller_code)};
|
580
|
+
block_func = #{anonymous_function(:proc_new,&rb_funcall_block_code)};
|
670
581
|
} else if (node == #{@callcc_node_gvar}) {
|
671
|
-
caller_func = #{anonymous_function(
|
672
|
-
block_func = #{anonymous_function(
|
582
|
+
caller_func = #{anonymous_function(:normal,&rb_funcall_caller_code)};
|
583
|
+
block_func = #{anonymous_function(:callcc,&rb_funcall_block_code)};
|
673
584
|
} else {
|
674
|
-
caller_func = #{anonymous_function(
|
675
|
-
block_func = #{anonymous_function(
|
585
|
+
caller_func = #{anonymous_function(:normal,&rb_funcall_caller_code)};
|
586
|
+
block_func = #{anonymous_function(:normal,&rb_funcall_block_code)};
|
676
587
|
}
|
677
588
|
|
678
589
|
|
679
|
-
|
590
|
+
last_expression = rb_iterate(
|
680
591
|
caller_func,
|
681
592
|
(VALUE)pframe,
|
682
593
|
block_func,
|
@@ -688,7 +599,7 @@ module FastRuby
|
|
688
599
|
current_plocals = pframe->thread_data->last_plocals;
|
689
600
|
while (current_plocals) {
|
690
601
|
current_plocals->active = Qfalse;
|
691
|
-
current_plocals = (typeof(current_plocals))
|
602
|
+
current_plocals = (typeof(current_plocals))(current_plocals->parent_locals);
|
692
603
|
}
|
693
604
|
|
694
605
|
// restore last_plocals
|
@@ -699,57 +610,83 @@ module FastRuby
|
|
699
610
|
|
700
611
|
while (current_plocals) {
|
701
612
|
current_plocals->active = Qtrue;
|
702
|
-
current_plocals = (typeof(current_plocals))
|
613
|
+
current_plocals = (typeof(current_plocals))(current_plocals->parent_locals);
|
703
614
|
}
|
704
615
|
}
|
705
|
-
|
706
|
-
return ret;
|
707
|
-
"), true), precode, postcode
|
616
|
+
", true), precode, postcode
|
708
617
|
)
|
709
618
|
};
|
710
619
|
"
|
711
620
|
|
712
621
|
recvtype = nil if call_args_tree.size > 1 ? call_args_tree.last[0] == :splat : false
|
713
622
|
unless recvtype
|
714
|
-
|
715
|
-
#{funcall_call_code}
|
716
|
-
|
623
|
+
if result_var
|
624
|
+
"#{result_var} = #{funcall_call_code};"
|
625
|
+
else
|
626
|
+
funcall_call_code
|
627
|
+
end
|
717
628
|
else
|
718
629
|
encoded_address = encode_address(recvtype,signature,mname,call_tree,inference_complete,convention_global_name)
|
719
630
|
|
720
|
-
|
631
|
+
if call_args_tree.size > 1
|
721
632
|
value_cast = ( ["VALUE"]*(call_tree[3].size) ).join(",") + ", VALUE, VALUE"
|
722
|
-
|
723
|
-
"
|
724
|
-
// call to #{call_tree[2]}
|
725
|
-
#{call_frame_struct_code}
|
726
|
-
|
727
|
-
VALUE ret = ((VALUE(*)(#{value_cast}))#{encoded_address})(#{str_recv}, (VALUE)&block, (VALUE)&call_frame, #{str_called_code_args});
|
728
|
-
plocals->call_frame = old_call_frame;
|
729
|
-
return ret;
|
730
|
-
"
|
633
|
+
strargs = "," + (0..call_args_tree.size-2).map{|i| "arg#{i}"}.join(",")
|
731
634
|
else
|
732
|
-
|
733
|
-
|
635
|
+
value_cast = "VALUE,VALUE,VALUE"
|
636
|
+
strargs = ""
|
637
|
+
end
|
734
638
|
|
639
|
+
fastruby_call_code = "
|
735
640
|
// call to #{call_tree[2]}
|
736
|
-
|
737
|
-
|
738
|
-
|
641
|
+
#{
|
642
|
+
if call_args_tree.size > 1
|
643
|
+
str_evaluate_args
|
644
|
+
end
|
645
|
+
};
|
646
|
+
|
647
|
+
VALUE recv = plocals->self;
|
648
|
+
|
649
|
+
#{
|
650
|
+
if recv_tree
|
651
|
+
to_c recv_tree, "recv"
|
652
|
+
end
|
653
|
+
}
|
654
|
+
|
655
|
+
ret = ((VALUE(*)(#{value_cast}))#{encoded_address})(recv, (VALUE)&block, (VALUE)&call_frame #{strargs});
|
739
656
|
"
|
740
|
-
end
|
741
657
|
|
742
|
-
|
658
|
+
code = "
|
743
659
|
if (#{@last_address_name} == 0) {
|
744
|
-
#{funcall_call_code}
|
660
|
+
return #{funcall_call_code};
|
745
661
|
} else {
|
662
|
+
#{if recvtype and inference_complete
|
663
|
+
"if (*#{@last_address_name} == 0) {
|
664
|
+
rb_funcall(#{literal_value recvtype},#{intern_num :build}, 2, #{literal_value signature}, #{literal_value mname});
|
665
|
+
}
|
666
|
+
"
|
667
|
+
end
|
668
|
+
}
|
746
669
|
if (*#{@last_address_name} == 0) {
|
747
|
-
#{funcall_call_code}
|
670
|
+
return #{funcall_call_code};
|
748
671
|
} else {
|
749
672
|
#{fastruby_call_code}
|
750
673
|
}
|
751
674
|
}
|
752
675
|
"
|
676
|
+
|
677
|
+
fastruby_precode = " #{@block_struct} block;
|
678
|
+
|
679
|
+
block.block_function_address = ((void*)#{anonymous_function(&block_code)});
|
680
|
+
block.block_function_param = ((void*)plocals);
|
681
|
+
block.proc = Qnil;
|
682
|
+
"
|
683
|
+
|
684
|
+
if result_var
|
685
|
+
"#{result_var} = #{frame_call(code,fastruby_precode,"")}"
|
686
|
+
else
|
687
|
+
frame_call(code,fastruby_precode,"")
|
688
|
+
end
|
689
|
+
|
753
690
|
end
|
754
691
|
end
|
755
692
|
end
|