fastruby 0.0.14 → 0.0.15
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +12 -0
- data/README +0 -2
- data/Rakefile +1 -1
- data/benchmarks/benchmark.rb +1 -0
- data/benchmarks/benchmark5.rb +3 -1
- data/ext/fastruby_base/fastruby_base.inl +2 -0
- data/lib/fastruby/builder.rb +18 -42
- data/lib/fastruby/exceptions.rb +8 -0
- data/lib/fastruby/getlocals.rb +17 -0
- data/lib/fastruby/object.rb +1 -31
- data/lib/fastruby/translator/modules/block.rb +44 -22
- data/lib/fastruby/translator/modules/call.rb +25 -1
- data/lib/fastruby/translator/modules/defn.rb +85 -57
- data/lib/fastruby/translator/modules/iter.rb +159 -46
- data/lib/fastruby/translator/modules/method_group.rb +7 -0
- data/lib/fastruby/translator/translator.rb +224 -245
- data/lib/fastruby.rb +1 -1
- data/lib/targetted +84 -0
- data/spec/block/arguments_spec.rb +214 -0
- data/spec/block/block_as_proc_spec.rb +98 -0
- data/spec/block/callcc_spec.rb +233 -0
- data/spec/block/proc_as_block_spec.rb +111 -0
- data/spec/call/base_call_spec.rb +3 -2
- data/spec/defn/default_args_spec.rb +303 -0
- data/spec/defn/multiple_args_spec.rb +35 -0
- data/spec/exception/base_spec.rb +26 -0
- metadata +10 -4
@@ -38,7 +38,6 @@ module FastRuby
|
|
38
38
|
attr_reader :no_cache
|
39
39
|
attr_reader :init_extra
|
40
40
|
attr_reader :extra_code
|
41
|
-
attr_reader :yield_signature
|
42
41
|
|
43
42
|
TranslatorModules.instance.load_under(FastRuby.fastruby_load_path + "/fastruby/translator/modules/")
|
44
43
|
TranslatorModules.instance.modls.each do |modl|
|
@@ -68,6 +67,12 @@ module FastRuby
|
|
68
67
|
void* block_function_param;
|
69
68
|
}"
|
70
69
|
|
70
|
+
extra_code << "
|
71
|
+
static void frb_jump_tag(int state) {
|
72
|
+
VALUE exception = rb_funcall(#{literal_value FastRuby::JumpTagException}, #{intern_num :new},1,INT2FIX(state));
|
73
|
+
rb_exc_raise(exception);
|
74
|
+
}
|
75
|
+
"
|
71
76
|
|
72
77
|
extra_code << "
|
73
78
|
#include \"node.h\"
|
@@ -98,11 +103,13 @@ module FastRuby
|
|
98
103
|
@lambda_node_gvar = add_global_name("NODE*", 0);
|
99
104
|
@proc_node_gvar = add_global_name("NODE*", 0);
|
100
105
|
@procnew_node_gvar = add_global_name("NODE*", 0);
|
106
|
+
@callcc_node_gvar = add_global_name("NODE*", 0);
|
101
107
|
|
102
108
|
init_extra << "
|
103
109
|
#{@lambda_node_gvar} = rb_method_node(rb_cObject, #{intern_num :lambda});
|
104
110
|
#{@proc_node_gvar} = rb_method_node(rb_cObject, #{intern_num :proc});
|
105
111
|
#{@procnew_node_gvar} = rb_method_node(CLASS_OF(rb_cProc), #{intern_num :new});
|
112
|
+
#{@callcc_node_gvar} = rb_method_node(rb_mKernel, #{intern_num :callcc});
|
106
113
|
"
|
107
114
|
|
108
115
|
@common_func = common_func
|
@@ -145,6 +152,7 @@ module FastRuby
|
|
145
152
|
*/
|
146
153
|
|
147
154
|
"
|
155
|
+
|
148
156
|
end
|
149
157
|
end
|
150
158
|
|
@@ -161,7 +169,7 @@ module FastRuby
|
|
161
169
|
name
|
162
170
|
end
|
163
171
|
|
164
|
-
def frame_call(inner_code)
|
172
|
+
def frame_call(inner_code, precode = "", postcode = "")
|
165
173
|
inline_block "
|
166
174
|
|
167
175
|
|
@@ -181,24 +189,33 @@ module FastRuby
|
|
181
189
|
VALUE old_call_frame = plocals->call_frame;
|
182
190
|
plocals->call_frame = LONG2FIX(&call_frame);
|
183
191
|
|
192
|
+
#{precode}
|
193
|
+
|
184
194
|
int aux = setjmp(call_frame.jmp);
|
185
195
|
if (aux != 0) {
|
186
196
|
if (call_frame.targetted == 0) {
|
197
|
+
#{postcode}
|
187
198
|
longjmp(old_pframe->jmp,aux);
|
188
199
|
}
|
189
200
|
|
190
201
|
if (aux == FASTRUBY_TAG_BREAK) {
|
191
202
|
plocals->call_frame = old_call_frame;
|
203
|
+
#{postcode}
|
192
204
|
return call_frame.return_value;
|
193
205
|
} else if (aux == FASTRUBY_TAG_RETRY ) {
|
194
206
|
// do nothing and let the call execute again
|
195
207
|
} else {
|
196
208
|
plocals->call_frame = old_call_frame;
|
209
|
+
#{postcode}
|
197
210
|
return call_frame.return_value;
|
198
211
|
}
|
199
212
|
}
|
213
|
+
|
200
214
|
|
201
215
|
VALUE ret = #{inner_code};
|
216
|
+
|
217
|
+
#{postcode}
|
218
|
+
|
202
219
|
plocals->call_frame = old_call_frame;
|
203
220
|
return ret;
|
204
221
|
"
|
@@ -207,6 +224,7 @@ module FastRuby
|
|
207
224
|
def initialize_method_structs(args_tree)
|
208
225
|
@locals_struct = "struct {
|
209
226
|
VALUE return_value;
|
227
|
+
VALUE parent_locals;
|
210
228
|
VALUE pframe;
|
211
229
|
VALUE block_function_address;
|
212
230
|
VALUE block_function_param;
|
@@ -214,94 +232,10 @@ module FastRuby
|
|
214
232
|
VALUE active;
|
215
233
|
VALUE targetted;
|
216
234
|
#{@locals.map{|l| "VALUE #{l};\n"}.join}
|
217
|
-
#{args_tree[1..-1].map{|arg| "VALUE #{arg.to_s.gsub("*","")};\n"}.join};
|
218
235
|
}"
|
219
236
|
|
220
237
|
end
|
221
238
|
|
222
|
-
def to_c_method_defs(tree)
|
223
|
-
|
224
|
-
method_name = tree[2]
|
225
|
-
args_tree = tree[3]
|
226
|
-
|
227
|
-
impl_tree = tree[4][1]
|
228
|
-
|
229
|
-
initialize_method_structs(args_tree)
|
230
|
-
|
231
|
-
strargs = if args_tree.size > 1
|
232
|
-
|
233
|
-
"VALUE self, void* block_address, VALUE block_param, void* _parent_frame, #{args_tree[1..-1].map{|arg| "VALUE #{arg.to_s.gsub("*","")}" }.join(",") }"
|
234
|
-
else
|
235
|
-
"VALUE self, void* block_address, VALUE block_param, void* _parent_frame"
|
236
|
-
end
|
237
|
-
|
238
|
-
extra_code << "static VALUE #{@alt_method_name + "_real"}(#{strargs}) {
|
239
|
-
#{func_frame}
|
240
|
-
|
241
|
-
#{args_tree[1..-1].map { |arg|
|
242
|
-
arg = arg.to_s
|
243
|
-
arg.gsub!("*","")
|
244
|
-
"plocals->#{arg} = #{arg};\n"
|
245
|
-
}.join("") }
|
246
|
-
|
247
|
-
plocals->block_function_address = LONG2FIX(block_address);
|
248
|
-
plocals->block_function_param = LONG2FIX(block_param);
|
249
|
-
|
250
|
-
return #{to_c impl_tree};
|
251
|
-
}"
|
252
|
-
|
253
|
-
strargs2 = if args_tree.size > 1
|
254
|
-
"VALUE self, #{args_tree[1..-1].map{|arg| "VALUE #{arg}" }.join(",") }"
|
255
|
-
else
|
256
|
-
"VALUE self"
|
257
|
-
end
|
258
|
-
|
259
|
-
value_cast = ( ["VALUE"]*(args_tree.size+1) ).join(",")
|
260
|
-
strmethodargs = ""
|
261
|
-
|
262
|
-
if args_tree.size > 1
|
263
|
-
strmethodargs = "self,block_address,block_param,&frame,#{args_tree[1..-1].map(&:to_s).join(",") }"
|
264
|
-
else
|
265
|
-
strmethodargs = "self,block_address,block_param,&frame"
|
266
|
-
end
|
267
|
-
|
268
|
-
"
|
269
|
-
VALUE #{@alt_method_name}(#{strargs2}) {
|
270
|
-
#{@frame_struct} frame;
|
271
|
-
int argc = #{args_tree.size};
|
272
|
-
void* block_address = 0;
|
273
|
-
VALUE block_param = Qnil;
|
274
|
-
|
275
|
-
frame.plocals = 0;
|
276
|
-
frame.parent_frame = 0;
|
277
|
-
frame.return_value = Qnil;
|
278
|
-
frame.rescue = 0;
|
279
|
-
frame.targetted = 0;
|
280
|
-
frame.thread_data = rb_current_thread_data();
|
281
|
-
|
282
|
-
if (rb_block_given_p()) {
|
283
|
-
block_address = #{
|
284
|
-
anonymous_function{|name|
|
285
|
-
"static VALUE #{name}(int argc, VALUE* argv, VALUE param) {
|
286
|
-
return rb_yield_splat(rb_ary_new4(argc,argv));
|
287
|
-
}"
|
288
|
-
}
|
289
|
-
};
|
290
|
-
|
291
|
-
block_param = 0;
|
292
|
-
}
|
293
|
-
|
294
|
-
int aux = setjmp(frame.jmp);
|
295
|
-
if (aux != 0) {
|
296
|
-
rb_funcall(self, #{intern_num :raise}, 1, frame.thread_data->exception);
|
297
|
-
}
|
298
|
-
|
299
|
-
|
300
|
-
return #{@alt_method_name + "_real"}(#{strmethodargs});
|
301
|
-
}
|
302
|
-
"
|
303
|
-
end
|
304
|
-
|
305
239
|
def add_main
|
306
240
|
if options[:main]
|
307
241
|
|
@@ -374,20 +308,31 @@ module FastRuby
|
|
374
308
|
end
|
375
309
|
|
376
310
|
def to_c_method(tree, signature = nil)
|
377
|
-
|
378
|
-
|
379
|
-
|
311
|
+
|
312
|
+
if tree[0] == :defn
|
313
|
+
method_name = tree[1]
|
314
|
+
original_args_tree = tree[2]
|
315
|
+
block_argument = tree[2].find{|x| x.to_s[0] == ?&}
|
316
|
+
impl_tree = tree[3][1]
|
317
|
+
elsif tree[0] == :defs
|
318
|
+
method_name = tree[2]
|
319
|
+
original_args_tree = tree[3]
|
320
|
+
block_argument = tree[3].find{|x| x.to_s[0] == ?&}
|
321
|
+
impl_tree = tree[4][1]
|
322
|
+
end
|
323
|
+
|
324
|
+
args_tree = original_args_tree.select{|x| x.to_s[0] != ?&}
|
380
325
|
|
381
326
|
if (options[:main])
|
382
|
-
initialize_method_structs(
|
327
|
+
initialize_method_structs(original_args_tree)
|
383
328
|
|
384
329
|
strargs = if args_tree.size > 1
|
385
|
-
"VALUE block, VALUE _parent_frame, #{(0..signature.size-1).map{|x| "VALUE arg#{x}"}.join(",")}"
|
330
|
+
"VALUE self, VALUE block, VALUE _parent_frame, #{(0..signature.size-1).map{|x| "VALUE arg#{x}"}.join(",")}"
|
386
331
|
else
|
387
|
-
"VALUE block, VALUE _parent_frame"
|
332
|
+
"VALUE self, VALUE block, VALUE _parent_frame"
|
388
333
|
end
|
389
334
|
|
390
|
-
ret = "VALUE #{@alt_method_name || method_name}() {
|
335
|
+
ret = "VALUE #{@alt_method_name || method_name}(VALUE self) {
|
391
336
|
|
392
337
|
#{@locals_struct} *plocals;
|
393
338
|
#{@frame_struct} frame;
|
@@ -404,7 +349,7 @@ module FastRuby
|
|
404
349
|
VALUE rb_previous_stack_chunk = Qnil;
|
405
350
|
VALUE rb_stack_chunk = frame.thread_data->rb_stack_chunk;
|
406
351
|
struct STACKCHUNK* stack_chunk = 0;
|
407
|
-
|
352
|
+
|
408
353
|
if (rb_stack_chunk != Qnil) {
|
409
354
|
Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
|
410
355
|
}
|
@@ -425,6 +370,11 @@ module FastRuby
|
|
425
370
|
int previous_stack_position = stack_chunk_get_current_position(stack_chunk);
|
426
371
|
|
427
372
|
plocals = (typeof(plocals))stack_chunk_alloc(stack_chunk ,sizeof(typeof(*plocals))/sizeof(void*));
|
373
|
+
|
374
|
+
plocals->parent_locals = LONG2FIX(frame.thread_data->last_plocals);
|
375
|
+
void* old_parent_locals = frame.thread_data->last_plocals;
|
376
|
+
frame.thread_data->last_plocals = plocals;
|
377
|
+
|
428
378
|
plocals->active = Qtrue;
|
429
379
|
plocals->targetted = Qfalse;
|
430
380
|
plocals->pframe = LONG2FIX(&frame);
|
@@ -444,6 +394,7 @@ module FastRuby
|
|
444
394
|
}
|
445
395
|
|
446
396
|
plocals->active = Qfalse;
|
397
|
+
frame.thread_data->last_plocals = old_parent_locals;
|
447
398
|
return plocals->return_value;
|
448
399
|
}
|
449
400
|
|
@@ -468,72 +419,131 @@ module FastRuby
|
|
468
419
|
}
|
469
420
|
|
470
421
|
plocals->active = Qfalse;
|
422
|
+
|
423
|
+
frame.thread_data->last_plocals = old_parent_locals;
|
471
424
|
return ret;
|
472
425
|
|
473
426
|
}"
|
474
427
|
|
475
428
|
add_main
|
476
|
-
ret
|
429
|
+
extra_code << ret
|
477
430
|
else
|
478
431
|
|
479
|
-
initialize_method_structs(
|
480
|
-
|
481
|
-
strargs = if args_tree.size > 1
|
482
|
-
"VALUE block, VALUE _parent_frame, #{(0..signature.size-1).map{|x| "VALUE arg#{x}"}.join(",")}"
|
483
|
-
else
|
484
|
-
"VALUE block, VALUE _parent_frame"
|
485
|
-
end
|
432
|
+
initialize_method_structs(original_args_tree)
|
486
433
|
|
487
|
-
|
434
|
+
strargs = "VALUE self, VALUE block, VALUE _parent_frame, int argc, VALUE* argv"
|
488
435
|
|
489
|
-
|
436
|
+
splat_arg = args_tree[1..-1].find{|x| x.to_s.match(/\*/) }
|
437
|
+
|
438
|
+
maxargnum = args_tree[1..-1].count{ |x|
|
439
|
+
if x.instance_of? Symbol
|
440
|
+
not x.to_s.match(/\*/) and not x.to_s.match(/\&/)
|
441
|
+
else
|
442
|
+
false
|
443
|
+
end
|
444
|
+
}
|
490
445
|
|
491
|
-
|
446
|
+
minargnum = maxargnum
|
492
447
|
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
448
|
+
args_tree[1..-1].each do |subtree|
|
449
|
+
unless subtree.instance_of? Symbol
|
450
|
+
if subtree[0] == :block
|
451
|
+
minargnum = minargnum - (subtree.size-1)
|
452
|
+
end
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
if args_tree[1..-1].find{|x| x.to_s.match(/\*/)}
|
457
|
+
maxargnum = 2147483647
|
458
|
+
end
|
459
|
+
|
460
|
+
read_arguments_code = ""
|
461
|
+
|
506
462
|
|
507
|
-
|
463
|
+
validate_arguments_code = if signature.size-1 < minargnum
|
508
464
|
"
|
465
|
+
rb_raise(rb_eArgError, \"wrong number of arguments (#{signature.size-1} for #{minargnum})\");
|
509
466
|
"
|
510
|
-
|
467
|
+
elsif signature.size-1 > maxargnum
|
511
468
|
"
|
512
|
-
rb_raise(rb_eArgError, \"wrong number of arguments (#{signature.size} for #{
|
469
|
+
rb_raise(rb_eArgError, \"wrong number of arguments (#{signature.size-1} for #{maxargnum})\");
|
513
470
|
"
|
514
|
-
end
|
515
|
-
|
516
471
|
else
|
472
|
+
|
473
|
+
default_block_tree = args_tree[1..-1].find{|subtree|
|
474
|
+
unless subtree.instance_of? Symbol
|
475
|
+
if subtree[0] == :block
|
476
|
+
next true
|
477
|
+
end
|
478
|
+
end
|
479
|
+
|
480
|
+
false
|
481
|
+
}
|
482
|
+
|
483
|
+
i = -1
|
484
|
+
|
485
|
+
normalargsnum = args_tree[1..-1].count{|subtree|
|
486
|
+
if subtree.instance_of? Symbol
|
487
|
+
unless subtree.to_s.match(/\*/) or subtree.to_s.match(/\&/)
|
488
|
+
next true
|
489
|
+
end
|
490
|
+
end
|
491
|
+
|
492
|
+
false
|
493
|
+
}
|
494
|
+
|
495
|
+
read_arguments_code = args_tree[1..-1].map { |arg_|
|
496
|
+
arg = arg_.to_s
|
497
|
+
i = i + 1
|
498
|
+
|
499
|
+
if i < normalargsnum
|
500
|
+
if i < signature.size-1
|
501
|
+
"plocals->#{arg} = argv[#{i}];\n"
|
502
|
+
else
|
503
|
+
|
504
|
+
if default_block_tree
|
505
|
+
initialize_tree = default_block_tree[1..-1].find{|subtree| subtree[1] == arg_}
|
506
|
+
if initialize_tree
|
507
|
+
to_c(initialize_tree) + ";\n"
|
508
|
+
else
|
509
|
+
""
|
510
|
+
end
|
511
|
+
else
|
512
|
+
";\n"
|
513
|
+
end
|
514
|
+
end
|
515
|
+
else
|
516
|
+
""
|
517
|
+
end
|
518
|
+
}.join("")
|
519
|
+
|
520
|
+
if splat_arg
|
521
|
+
if signature.size-1 < normalargsnum then
|
522
|
+
read_arguments_code << "
|
523
|
+
plocals->#{splat_arg.to_s.gsub("*","")} = rb_ary_new3(0);
|
524
|
+
"
|
525
|
+
else
|
526
|
+
read_arguments_code << "
|
527
|
+
plocals->#{splat_arg.to_s.gsub("*","")} = rb_ary_new4(
|
528
|
+
#{(signature.size-1) - (normalargsnum)}, argv+#{normalargsnum}
|
529
|
+
);
|
530
|
+
"
|
531
|
+
end
|
532
|
+
|
533
|
+
end
|
517
534
|
|
518
|
-
i = -1
|
519
535
|
|
520
|
-
|
521
|
-
|
522
|
-
i = i + 1
|
523
|
-
"plocals->#{arg} = arg#{i};\n"
|
524
|
-
}.join("")
|
536
|
+
""
|
537
|
+
end
|
525
538
|
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
end
|
534
|
-
|
539
|
+
if block_argument
|
540
|
+
|
541
|
+
proc_reyield_block_tree = s(:iter, s(:call, nil, :proc, s(:arglist)), s(:masgn, s(:array, s(:splat, s(:lasgn, :__xproc_arguments)))), s(:yield, s(:splat, s(:lvar, :__xproc_arguments))))
|
542
|
+
|
543
|
+
read_arguments_code << "
|
544
|
+
plocals->#{block_argument.to_s.gsub("&","")} = #{to_c proc_reyield_block_tree.to_fastruby_sexp};
|
545
|
+
"
|
535
546
|
end
|
536
|
-
|
537
547
|
|
538
548
|
ret = "VALUE #{@alt_method_name || method_name}(#{strargs}) {
|
539
549
|
#{validate_arguments_code}
|
@@ -576,6 +586,11 @@ module FastRuby
|
|
576
586
|
int previous_stack_position = stack_chunk_get_current_position(stack_chunk);
|
577
587
|
|
578
588
|
plocals = (typeof(plocals))stack_chunk_alloc(stack_chunk ,sizeof(typeof(*plocals))/sizeof(void*));
|
589
|
+
|
590
|
+
plocals->parent_locals = LONG2FIX(frame.thread_data->last_plocals);
|
591
|
+
void* old_parent_locals = frame.thread_data->last_plocals;
|
592
|
+
frame.thread_data->last_plocals = plocals;
|
593
|
+
|
579
594
|
frame.plocals = plocals;
|
580
595
|
plocals->active = Qtrue;
|
581
596
|
plocals->targetted = Qfalse;
|
@@ -598,10 +613,14 @@ module FastRuby
|
|
598
613
|
frame.thread_data->rb_stack_chunk = rb_previous_stack_chunk;
|
599
614
|
}
|
600
615
|
|
601
|
-
if (plocals->targetted == Qfalse) {
|
616
|
+
if (plocals->targetted == Qfalse || aux != FASTRUBY_TAG_RETURN) {
|
617
|
+
frame.thread_data->last_plocals = old_parent_locals;
|
618
|
+
|
602
619
|
longjmp(((typeof(pframe))_parent_frame)->jmp,aux);
|
603
620
|
}
|
604
621
|
|
622
|
+
frame.thread_data->last_plocals = old_parent_locals;
|
623
|
+
|
605
624
|
return plocals->return_value;
|
606
625
|
}
|
607
626
|
|
@@ -627,12 +646,21 @@ module FastRuby
|
|
627
646
|
}
|
628
647
|
|
629
648
|
plocals->active = Qfalse;
|
649
|
+
|
650
|
+
frame.thread_data->last_plocals = old_parent_locals;
|
651
|
+
|
630
652
|
return __ret;
|
631
653
|
}"
|
632
654
|
|
633
655
|
add_main
|
634
|
-
ret
|
656
|
+
extra_code << ret
|
635
657
|
end
|
658
|
+
|
659
|
+
"
|
660
|
+
static VALUE dummy_#{method_name}_#{alt_method_name}_#{rand(1000000000000000000000000000000000)}(VALUE a) {
|
661
|
+
return Qnil;
|
662
|
+
}
|
663
|
+
"
|
636
664
|
end
|
637
665
|
|
638
666
|
def locals_accessor
|
@@ -646,6 +674,7 @@ module FastRuby
|
|
646
674
|
@locals = locals
|
647
675
|
@locals_struct = "struct {
|
648
676
|
VALUE return_value;
|
677
|
+
VALUE parent_locals;
|
649
678
|
VALUE pframe;
|
650
679
|
VALUE block_function_address;
|
651
680
|
VALUE block_function_param;
|
@@ -687,16 +716,6 @@ module FastRuby
|
|
687
716
|
@on_block = old_on_block
|
688
717
|
end
|
689
718
|
|
690
|
-
def with_extra_inference(extra_inference)
|
691
|
-
previous_infer_lvar_map = @infer_lvar_map
|
692
|
-
begin
|
693
|
-
@infer_lvar_map = @infer_lvar_map.merge(extra_inference)
|
694
|
-
yield
|
695
|
-
ensure
|
696
|
-
@infer_lvar_map = previous_infer_lvar_map
|
697
|
-
end
|
698
|
-
end
|
699
|
-
|
700
719
|
def directive(tree)
|
701
720
|
recv = tree[1]
|
702
721
|
mname = tree[2]
|
@@ -779,14 +798,20 @@ module FastRuby
|
|
779
798
|
def protected_block(inner_code, always_rescue = false,repass_var = nil, nolocals = false)
|
780
799
|
body = nil
|
781
800
|
rescue_args = nil
|
782
|
-
|
801
|
+
|
783
802
|
body = anonymous_function{ |name| "
|
784
803
|
static VALUE #{name}(VALUE param) {
|
785
804
|
|
786
805
|
#{@frame_struct} frame;
|
787
806
|
|
788
807
|
typeof(frame)* pframe;
|
789
|
-
|
808
|
+
|
809
|
+
#{if repass_var
|
810
|
+
"typeof(frame)* parent_frame = ((typeof(pframe))((void**)param)[0]);"
|
811
|
+
else
|
812
|
+
"typeof(frame)* parent_frame = (typeof(pframe))param;"
|
813
|
+
end
|
814
|
+
}
|
790
815
|
|
791
816
|
frame.parent_frame = 0;
|
792
817
|
frame.return_value = Qnil;
|
@@ -794,6 +819,7 @@ module FastRuby
|
|
794
819
|
frame.last_error = Qnil;
|
795
820
|
frame.targetted = 0;
|
796
821
|
frame.thread_data = parent_frame->thread_data;
|
822
|
+
frame.next_recv = parent_frame->next_recv;
|
797
823
|
if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
|
798
824
|
|
799
825
|
pframe = &frame;
|
@@ -810,84 +836,69 @@ module FastRuby
|
|
810
836
|
if (frame.targetted == 1) {
|
811
837
|
return frame.return_value;
|
812
838
|
} else {
|
813
|
-
|
839
|
+
frb_jump_tag(aux);
|
814
840
|
}
|
815
841
|
}
|
816
842
|
|
817
|
-
|
843
|
+
#{if repass_var
|
844
|
+
"VALUE #{repass_var} = (VALUE)((void**)param)[1];"
|
845
|
+
end
|
846
|
+
}
|
818
847
|
return #{inner_code};
|
819
848
|
}
|
820
849
|
"
|
821
850
|
}
|
822
851
|
|
852
|
+
if repass_var
|
823
853
|
rescue_args = ""
|
824
854
|
rescue_args = "(VALUE)(VALUE[]){(VALUE)pframe,(VALUE)#{repass_var}}"
|
825
855
|
else
|
856
|
+
rescue_args = "(VALUE)pframe"
|
857
|
+
end
|
826
858
|
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
frame.rescue = 0;
|
837
|
-
frame.last_error = Qnil;
|
838
|
-
frame.targetted = 0;
|
839
|
-
frame.thread_data = parent_frame->thread_data;
|
840
|
-
if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
|
841
|
-
|
842
|
-
pframe = &frame;
|
843
|
-
|
844
|
-
#{
|
845
|
-
nolocals ? "frame.plocals = 0;" : "#{@locals_struct}* plocals = parent_frame->plocals;
|
846
|
-
frame.plocals = plocals;
|
847
|
-
"
|
848
|
-
}
|
849
|
-
|
850
|
-
int aux = setjmp(frame.jmp);
|
851
|
-
if (aux != 0) {
|
852
|
-
|
853
|
-
if (frame.targetted == 1) {
|
854
|
-
return frame.return_value;
|
855
|
-
} else {
|
856
|
-
rb_jump_tag(aux);
|
859
|
+
wrapper_code = "
|
860
|
+
if (str.state >= 0x80) {
|
861
|
+
longjmp(pframe->jmp, str.state);
|
862
|
+
} else {
|
863
|
+
if (str.last_error != Qnil) {
|
864
|
+
// raise emulation
|
865
|
+
pframe->thread_data->exception = str.last_error;
|
866
|
+
longjmp(pframe->jmp, FASTRUBY_TAG_RAISE);
|
867
|
+
return Qnil;
|
857
868
|
}
|
858
869
|
}
|
859
|
-
|
860
|
-
|
861
|
-
|
870
|
+
"
|
871
|
+
|
872
|
+
return_err_struct = "struct {
|
873
|
+
VALUE last_error;
|
874
|
+
int state;
|
875
|
+
}
|
862
876
|
"
|
863
|
-
}
|
864
|
-
|
865
|
-
rescue_args = "(VALUE)pframe"
|
866
|
-
end
|
867
|
-
|
868
|
-
wrapper_code = " if (state != 0) {
|
869
|
-
if (state < 0x80) {
|
870
877
|
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
878
|
+
rescue_body = anonymous_function{ |name| "
|
879
|
+
static VALUE #{name}(VALUE param, VALUE err) {
|
880
|
+
#{return_err_struct} *pstr = (void*)param;
|
881
|
+
|
882
|
+
if (rb_obj_is_instance_of(err, #{literal_value FastRuby::JumpTagException})) {
|
883
|
+
pstr->state = FIX2INT(rb_funcall(err, #{intern_num :state}, 0));
|
876
884
|
} else {
|
877
|
-
|
885
|
+
pstr->last_error = err;
|
878
886
|
}
|
879
|
-
|
880
|
-
|
887
|
+
|
888
|
+
return Qnil;
|
881
889
|
}
|
882
|
-
|
883
|
-
}
|
884
890
|
"
|
891
|
+
}
|
885
892
|
|
886
|
-
rescue_code = "
|
893
|
+
rescue_code = "rb_rescue2(#{body}, #{rescue_args}, #{rescue_body}, (VALUE)&str, rb_eException, (VALUE)0)"
|
887
894
|
|
888
895
|
if always_rescue
|
889
896
|
inline_block "
|
890
|
-
|
897
|
+
#{return_err_struct} str;
|
898
|
+
|
899
|
+
str.state = 0;
|
900
|
+
str.last_error = Qnil;
|
901
|
+
|
891
902
|
pframe->last_error = Qnil;
|
892
903
|
VALUE result = #{rescue_code};
|
893
904
|
|
@@ -898,7 +909,11 @@ module FastRuby
|
|
898
909
|
else
|
899
910
|
inline_block "
|
900
911
|
VALUE result;
|
901
|
-
|
912
|
+
#{return_err_struct} str;
|
913
|
+
|
914
|
+
str.state = 0;
|
915
|
+
str.last_error = Qnil;
|
916
|
+
|
902
917
|
pframe->last_error = Qnil;
|
903
918
|
|
904
919
|
if (pframe->rescue) {
|
@@ -913,42 +928,6 @@ module FastRuby
|
|
913
928
|
end
|
914
929
|
end
|
915
930
|
|
916
|
-
def func_frame
|
917
|
-
"
|
918
|
-
#{@locals_struct} *plocals = malloc(sizeof(typeof(*plocals)));
|
919
|
-
#{@frame_struct} frame;
|
920
|
-
#{@frame_struct} *pframe;
|
921
|
-
|
922
|
-
frame.plocals = plocals;
|
923
|
-
frame.parent_frame = (void*)_parent_frame;
|
924
|
-
frame.return_value = Qnil;
|
925
|
-
frame.rescue = 0;
|
926
|
-
frame.targetted = 0;
|
927
|
-
frame.thread_data = ((typeof(pframe))_parent_frame)->thread_data;
|
928
|
-
if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
|
929
|
-
|
930
|
-
plocals->pframe = LONG2FIX(&frame);
|
931
|
-
plocals->targetted = Qfalse;
|
932
|
-
|
933
|
-
pframe = (void*)&frame;
|
934
|
-
|
935
|
-
#{@block_struct} *pblock;
|
936
|
-
VALUE last_expression = Qnil;
|
937
|
-
|
938
|
-
int aux = setjmp(pframe->jmp);
|
939
|
-
if (aux != 0) {
|
940
|
-
|
941
|
-
if (plocals->targetted == Qfalse) {
|
942
|
-
longjmp(((typeof(pframe))_parent_frame)->jmp,aux);
|
943
|
-
}
|
944
|
-
|
945
|
-
return plocals->return_value;
|
946
|
-
}
|
947
|
-
|
948
|
-
plocals->self = self;
|
949
|
-
"
|
950
|
-
end
|
951
|
-
|
952
931
|
def c_escape(str)
|
953
932
|
str.inspect
|
954
933
|
end
|
@@ -1102,7 +1081,7 @@ module FastRuby
|
|
1102
1081
|
protected_block "rb_funcall(((VALUE*)method_arguments)[0], #{intern_num mname.to_sym}, #{args_tree.size-1}#{inprocstrargs});", false, "method_arguments"
|
1103
1082
|
};
|
1104
1083
|
} else {
|
1105
|
-
return ( (VALUE(*)(
|
1084
|
+
return ( (VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*)) (fptr) )(self,(VALUE)block,(VALUE)frame,#{args_tree.size-1},method_arguments+1);
|
1106
1085
|
}
|
1107
1086
|
}
|
1108
1087
|
"
|