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
@@ -49,8 +49,6 @@ module FastRuby
|
|
49
49
|
mobject = nil
|
50
50
|
len = nil
|
51
51
|
|
52
|
-
extra_inference = {}
|
53
|
-
|
54
52
|
if recvtype
|
55
53
|
|
56
54
|
inference_complete = true
|
@@ -64,31 +62,6 @@ module FastRuby
|
|
64
62
|
inference_complete = false
|
65
63
|
end
|
66
64
|
end
|
67
|
-
|
68
|
-
if recvtype.respond_to? :fastruby_method and inference_complete
|
69
|
-
method_tree = nil
|
70
|
-
begin
|
71
|
-
method_tree = recvtype.instance_method(call_tree[2]).fastruby.tree
|
72
|
-
rescue NoMethodError
|
73
|
-
end
|
74
|
-
|
75
|
-
if method_tree
|
76
|
-
mobject = recvtype.build(signature, call_tree[2])
|
77
|
-
yield_signature = mobject.yield_signature
|
78
|
-
|
79
|
-
if not args_tree
|
80
|
-
elsif args_tree.first == :lasgn
|
81
|
-
if yield_signature[0]
|
82
|
-
extra_inference[args_tree.last] = yield_signature[0]
|
83
|
-
end
|
84
|
-
elsif args_tree.first == :masgn
|
85
|
-
yield_args = args_tree[1][1..-1].map(&:last)
|
86
|
-
(0...yield_signature.size-1).each do |i|
|
87
|
-
extra_inference[yield_args[i]] = yield_signature[i]
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
65
|
end
|
93
66
|
|
94
67
|
anonymous_impl = tree[3]
|
@@ -103,8 +76,6 @@ module FastRuby
|
|
103
76
|
|
104
77
|
str_impl = ""
|
105
78
|
|
106
|
-
with_extra_inference(extra_inference) do
|
107
|
-
|
108
79
|
on_block do
|
109
80
|
# if impl_tree is a block, implement the last node with a return
|
110
81
|
if anonymous_impl
|
@@ -129,18 +100,41 @@ module FastRuby
|
|
129
100
|
str_impl = "last_expression = Qnil;"
|
130
101
|
end
|
131
102
|
end
|
132
|
-
end
|
133
|
-
|
134
103
|
|
135
104
|
if not args_tree
|
136
|
-
str_arg_initialization = ""
|
137
105
|
elsif args_tree.first == :lasgn
|
138
|
-
str_arg_initialization
|
106
|
+
str_arg_initialization << "plocals->#{args_tree[1]} = arg;"
|
139
107
|
elsif args_tree.first == :masgn
|
140
|
-
|
141
|
-
|
108
|
+
|
109
|
+
str_arg_initialization << "
|
110
|
+
{
|
111
|
+
if (TYPE(arg) != T_ARRAY) {
|
112
|
+
if (arg != Qnil) {
|
113
|
+
arg = rb_ary_new4(1,&arg);
|
114
|
+
} else {
|
115
|
+
arg = rb_ary_new2(0);
|
116
|
+
}
|
117
|
+
} else if (RARRAY(arg)->len <= 1) {
|
118
|
+
arg = rb_ary_new4(1,&arg);
|
119
|
+
}
|
120
|
+
}
|
121
|
+
"
|
122
|
+
|
123
|
+
arguments = args_tree[1][1..-1]
|
124
|
+
|
142
125
|
(0..arguments.size-1).each do |i|
|
143
|
-
|
126
|
+
arg = arguments[i]
|
127
|
+
if arg[0] == :lasgn
|
128
|
+
str_arg_initialization << "plocals->#{arguments[i].last} = rb_ary_entry(arg,#{i});\n"
|
129
|
+
elsif arg[0] == :splat
|
130
|
+
str_arg_initialization << "plocals->#{arg.last.last} = rb_ary_new2(RARRAY(arg)->len-#{i});\n
|
131
|
+
|
132
|
+
int i;
|
133
|
+
for (i=#{i};i<RARRAY(arg)->len;i++){
|
134
|
+
rb_ary_store(plocals->#{arg.last.last},i-#{i},rb_ary_entry(arg,i));
|
135
|
+
}
|
136
|
+
"
|
137
|
+
end
|
144
138
|
end
|
145
139
|
end
|
146
140
|
rb_funcall_caller_code = nil
|
@@ -339,7 +333,7 @@ module FastRuby
|
|
339
333
|
rb_raise(rb_eLocalJumpError,\"return from proc-closure\");
|
340
334
|
} else {
|
341
335
|
((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
|
342
|
-
|
336
|
+
frb_jump_tag(aux);
|
343
337
|
}
|
344
338
|
} else {
|
345
339
|
rb_raise(rb_eLocalJumpError, \"unexpected return\");
|
@@ -382,7 +376,7 @@ module FastRuby
|
|
382
376
|
} else if (aux == FASTRUBY_TAG_REDO) {
|
383
377
|
// do nothing and let execute the block again
|
384
378
|
} else {
|
385
|
-
|
379
|
+
frb_jump_tag(aux);
|
386
380
|
return frame.return_value;
|
387
381
|
}
|
388
382
|
}
|
@@ -396,6 +390,48 @@ module FastRuby
|
|
396
390
|
"
|
397
391
|
}
|
398
392
|
|
393
|
+
rb_funcall_block_code_callcc = proc { |name| "
|
394
|
+
static VALUE #{name}(VALUE arg, VALUE _plocals) {
|
395
|
+
// block for call to #{call_tree[2]}
|
396
|
+
VALUE last_expression = Qnil;
|
397
|
+
|
398
|
+
#{@frame_struct} frame;
|
399
|
+
#{@frame_struct} *pframe = (void*)&frame;
|
400
|
+
#{@locals_struct} *plocals = (void*)_plocals;
|
401
|
+
|
402
|
+
frame.plocals = plocals;
|
403
|
+
frame.parent_frame = 0;
|
404
|
+
frame.return_value = Qnil;
|
405
|
+
frame.rescue = 0;
|
406
|
+
frame.targetted = 0;
|
407
|
+
frame.thread_data = rb_current_thread_data();
|
408
|
+
|
409
|
+
int aux = setjmp(frame.jmp);
|
410
|
+
if (aux != 0) {
|
411
|
+
|
412
|
+
if (aux == FASTRUBY_TAG_NEXT) {
|
413
|
+
return pframe->thread_data->accumulator;
|
414
|
+
} else if (aux == FASTRUBY_TAG_REDO) {
|
415
|
+
// do nothing and let execute the block again
|
416
|
+
} else {
|
417
|
+
frb_jump_tag(aux);
|
418
|
+
return frame.return_value;
|
419
|
+
}
|
420
|
+
}
|
421
|
+
|
422
|
+
if (rb_obj_is_kind_of(arg,rb_cCont)) {
|
423
|
+
struct FASTRUBYTHREADDATA* thread_data = frame.thread_data;
|
424
|
+
rb_ivar_set(arg,#{intern_num :__stack_chunk},thread_data->rb_stack_chunk);
|
425
|
+
}
|
426
|
+
|
427
|
+
#{str_arg_initialization}
|
428
|
+
#{str_impl}
|
429
|
+
|
430
|
+
return last_expression;
|
431
|
+
}
|
432
|
+
"
|
433
|
+
}
|
434
|
+
|
399
435
|
|
400
436
|
fastruby_str_arg_initialization = ""
|
401
437
|
|
@@ -404,10 +440,22 @@ module FastRuby
|
|
404
440
|
elsif args_tree.first == :lasgn
|
405
441
|
fastruby_str_arg_initialization = "plocals->#{args_tree[1]} = argv[0];"
|
406
442
|
elsif args_tree.first == :masgn
|
407
|
-
arguments = args_tree[1][1..-1]
|
408
|
-
|
443
|
+
arguments = args_tree[1][1..-1]
|
444
|
+
|
409
445
|
(0..arguments.size-1).each do |i|
|
410
|
-
|
446
|
+
arg = arguments[i]
|
447
|
+
if arg[0] == :lasgn
|
448
|
+
fastruby_str_arg_initialization << "plocals->#{arg.last} = #{i} < argc ? argv[#{i}] : Qnil;\n"
|
449
|
+
elsif arg[0] == :splat
|
450
|
+
fastruby_str_arg_initialization << "plocals->#{arg.last.last} = rb_ary_new2(#{arguments.size-1-i});\n
|
451
|
+
{
|
452
|
+
int i;
|
453
|
+
for (i=#{i};i<argc;i++){
|
454
|
+
rb_ary_store(plocals->#{arg.last.last},i-#{i},argv[i]);
|
455
|
+
}
|
456
|
+
}
|
457
|
+
"
|
458
|
+
end
|
411
459
|
end
|
412
460
|
end
|
413
461
|
|
@@ -496,16 +544,55 @@ module FastRuby
|
|
496
544
|
}
|
497
545
|
"
|
498
546
|
|
547
|
+
precode = "
|
548
|
+
struct FASTRUBYTHREADDATA* thread_data = 0;
|
549
|
+
VALUE saved_rb_stack_chunk = Qnil;
|
550
|
+
|
551
|
+
pframe->next_recv = #{recv_tree ? to_c(recv_tree) : "plocals->self"};
|
552
|
+
|
553
|
+
NODE* node = rb_method_node(CLASS_OF(pframe->next_recv), #{intern_num mname});
|
554
|
+
|
555
|
+
if (node == #{@callcc_node_gvar}) {
|
556
|
+
|
557
|
+
// freeze all stacks
|
558
|
+
thread_data = rb_current_thread_data();
|
559
|
+
|
560
|
+
if (thread_data != 0) {
|
561
|
+
VALUE rb_stack_chunk = thread_data->rb_stack_chunk;
|
562
|
+
saved_rb_stack_chunk = rb_stack_chunk;
|
563
|
+
|
564
|
+
// freeze the complete chain of stack chunks
|
565
|
+
while (rb_stack_chunk != Qnil) {
|
566
|
+
struct STACKCHUNK* stack_chunk;
|
567
|
+
Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
|
568
|
+
|
569
|
+
stack_chunk_freeze(stack_chunk);
|
570
|
+
|
571
|
+
rb_stack_chunk = rb_ivar_get(rb_stack_chunk,#{intern_num :_parent_stack_chunk});
|
572
|
+
}
|
573
|
+
}
|
574
|
+
}
|
575
|
+
"
|
576
|
+
|
577
|
+
postcode = "
|
578
|
+
if (node == #{@callcc_node_gvar}) {
|
579
|
+
thread_data->rb_stack_chunk = saved_rb_stack_chunk;
|
580
|
+
}
|
581
|
+
"
|
582
|
+
|
583
|
+
|
499
584
|
funcall_call_code = "
|
500
585
|
return #{
|
501
586
|
frame_call(
|
502
587
|
protected_block(inline_block("
|
503
|
-
|
504
|
-
pframe->next_recv = #{recv_tree ? to_c(recv_tree) : "plocals->self"};
|
505
|
-
|
588
|
+
|
506
589
|
NODE* node = rb_method_node(CLASS_OF(pframe->next_recv), #{intern_num mname});
|
507
590
|
void* caller_func;
|
508
591
|
void* block_func;
|
592
|
+
typeof(plocals) current_plocals;
|
593
|
+
|
594
|
+
if (pframe->thread_data == 0) pframe->thread_data = rb_current_thread_data();
|
595
|
+
void* last_plocals = pframe->thread_data->last_plocals;
|
509
596
|
|
510
597
|
if (
|
511
598
|
node == #{@proc_node_gvar} ||
|
@@ -517,18 +604,44 @@ module FastRuby
|
|
517
604
|
} else if (node == #{@procnew_node_gvar} && pframe->next_recv == rb_cProc) {
|
518
605
|
caller_func = #{anonymous_function(&rb_funcall_caller_code_with_lambda)};
|
519
606
|
block_func = #{anonymous_function(&rb_funcall_block_code_proc_new)};
|
607
|
+
} else if (node == #{@callcc_node_gvar}) {
|
608
|
+
caller_func = #{anonymous_function(&rb_funcall_caller_code)};
|
609
|
+
block_func = #{anonymous_function(&rb_funcall_block_code_callcc)};
|
520
610
|
} else {
|
521
611
|
caller_func = #{anonymous_function(&rb_funcall_caller_code)};
|
522
612
|
block_func = #{anonymous_function(&rb_funcall_block_code)};
|
523
613
|
}
|
614
|
+
|
524
615
|
|
525
|
-
|
616
|
+
VALUE ret = rb_iterate(
|
526
617
|
caller_func,
|
527
618
|
(VALUE)pframe,
|
528
619
|
block_func,
|
529
620
|
(VALUE)plocals);
|
530
621
|
|
531
|
-
|
622
|
+
if (node == #{@callcc_node_gvar}) {
|
623
|
+
|
624
|
+
// remove active flags of abandoned stack
|
625
|
+
current_plocals = pframe->thread_data->last_plocals;
|
626
|
+
while (current_plocals) {
|
627
|
+
current_plocals->active = Qfalse;
|
628
|
+
current_plocals = (typeof(current_plocals))FIX2LONG(current_plocals->parent_locals);
|
629
|
+
}
|
630
|
+
|
631
|
+
// restore last_plocals
|
632
|
+
pframe->thread_data->last_plocals = last_plocals;
|
633
|
+
|
634
|
+
// mark all scopes as active
|
635
|
+
current_plocals = last_plocals;
|
636
|
+
|
637
|
+
while (current_plocals) {
|
638
|
+
current_plocals->active = Qtrue;
|
639
|
+
current_plocals = (typeof(current_plocals))FIX2LONG(current_plocals->parent_locals);
|
640
|
+
}
|
641
|
+
}
|
642
|
+
|
643
|
+
return ret;
|
644
|
+
"), true), precode, postcode
|
532
645
|
)
|
533
646
|
};
|
534
647
|
"
|
@@ -112,6 +112,10 @@ private
|
|
112
112
|
|
113
113
|
plocals = (typeof(plocals))stack_chunk_alloc(stack_chunk ,sizeof(typeof(*plocals))/sizeof(void*));
|
114
114
|
|
115
|
+
plocals->parent_locals = LONG2FIX(frame.thread_data->last_plocals);
|
116
|
+
void* old_parent_locals = frame.thread_data->last_plocals;
|
117
|
+
frame.thread_data->last_plocals = plocals;
|
118
|
+
|
115
119
|
frame.plocals = plocals;
|
116
120
|
plocals->active = Qtrue;
|
117
121
|
plocals->self = self;
|
@@ -128,6 +132,9 @@ private
|
|
128
132
|
}
|
129
133
|
|
130
134
|
plocals->active = Qfalse;
|
135
|
+
|
136
|
+
frame.thread_data->last_plocals = old_parent_locals;
|
137
|
+
|
131
138
|
return Qnil;
|
132
139
|
}
|
133
140
|
"
|