fastruby 0.0.9 → 0.0.10
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 +6 -0
- data/Rakefile +1 -1
- data/lib/fastruby/exceptions.rb +0 -10
- data/lib/fastruby/translator.rb +333 -382
- data/lib/fastruby.rb +1 -1
- data/spec/block/redo_spec.rb +67 -0
- data/spec/block/retry_spec.rb +135 -0
- data/spec/exception/base_spec.rb +39 -0
- data/spec/exception/ensure_spec.rb +52 -0
- data/spec/{exception_spec.rb → exception/exc_trap_spec.rb} +0 -154
- data/spec/exception/syntaxis_spec.rb +89 -0
- data/spec/flow_control/for_spec.rb +40 -0
- data/spec/jump/next_spec.rb +36 -0
- metadata +12 -6
- data/spec/block/callcc_spec.rb +0 -115
data/lib/fastruby/translator.rb
CHANGED
@@ -46,15 +46,14 @@ module FastRuby
|
|
46
46
|
@init_extra = Array.new
|
47
47
|
@frame_struct = "struct {
|
48
48
|
void* parent_frame;
|
49
|
-
void* target_frame;
|
50
49
|
void* plocals;
|
51
50
|
jmp_buf jmp;
|
52
51
|
VALUE return_value;
|
53
|
-
VALUE exception;
|
54
52
|
int rescue;
|
55
53
|
VALUE last_error;
|
56
|
-
void* stack_chunk;
|
57
54
|
VALUE next_recv;
|
55
|
+
int targetted;
|
56
|
+
struct FASTRUBYTHREADDATA* thread_data;
|
58
57
|
}"
|
59
58
|
|
60
59
|
@block_struct = "struct {
|
@@ -66,6 +65,14 @@ module FastRuby
|
|
66
65
|
extra_code << "
|
67
66
|
#include \"node.h\"
|
68
67
|
|
68
|
+
#define FASTRUBY_TAG_RETURN 0x80
|
69
|
+
#define FASTRUBY_TAG_NEXT 0x81
|
70
|
+
#define FASTRUBY_TAG_BREAK 0x82
|
71
|
+
#define FASTRUBY_TAG_RAISE 0x83
|
72
|
+
#define FASTRUBY_TAG_REDO 0x84
|
73
|
+
#define FASTRUBY_TAG_RETRY 0x85
|
74
|
+
#define TAG_RAISE 0x6
|
75
|
+
|
69
76
|
#ifndef __INLINE_FASTRUBY_BASE
|
70
77
|
#include \"#{FastRuby.fastruby_load_path}/../ext/fastruby_base/fastruby_base.inl\"
|
71
78
|
#define __INLINE_FASTRUBY_BASE
|
@@ -130,63 +137,10 @@ module FastRuby
|
|
130
137
|
#{caller.join("\n")}
|
131
138
|
*/
|
132
139
|
|
133
|
-
"
|
134
|
-
extra_code << "static struct STACKCHUNKREFRENCE* get_stack_chunk_reference_from_context() {
|
135
|
-
struct STACKCHUNKREFERENCE* stack_chunk_reference;
|
136
|
-
VALUE current_thread = rb_thread_current();
|
137
|
-
VALUE rb_stack_chunk_reference = rb_ivar_get(current_thread,#{intern_num :_fastruby_stack_chunk_reference});
|
138
|
-
if (rb_stack_chunk_reference == Qnil) {
|
139
|
-
rb_stack_chunk_reference = rb_stack_chunk_reference_create();
|
140
|
-
rb_ivar_set(current_thread,#{intern_num :_fastruby_stack_chunk_reference},rb_stack_chunk_reference);
|
141
|
-
}
|
142
|
-
|
143
|
-
Data_Get_Struct(rb_stack_chunk_reference,struct STACKCHUNKREFERENCE,stack_chunk_reference);
|
144
|
-
|
145
|
-
return (void*)stack_chunk_reference;
|
146
|
-
}
|
147
|
-
|
148
|
-
static struct STACKCHUNK* get_stack_chunk_from_context(
|
149
|
-
struct STACKCHUNKREFERENCE** stack_chunk_reference,
|
150
|
-
VALUE* rb_stack_chunk
|
151
|
-
) {
|
152
|
-
struct STACKCHUNK* stack_chunk = 0;
|
153
|
-
*stack_chunk_reference = (void*)get_stack_chunk_reference_from_context();
|
154
|
-
*rb_stack_chunk = stack_chunk_reference_retrieve(*stack_chunk_reference);
|
155
|
-
if (*rb_stack_chunk != Qnil) {
|
156
|
-
Data_Get_Struct(*rb_stack_chunk,void,stack_chunk);
|
157
|
-
}
|
158
|
-
|
159
|
-
return stack_chunk;
|
160
|
-
}
|
161
|
-
|
162
|
-
static struct STACKCHUNK* create_stack_chunk_from_context(
|
163
|
-
struct STACKCHUNKREFERENCE** stack_chunk_reference,
|
164
|
-
VALUE* rb_stack_chunk_p
|
165
|
-
) {
|
166
|
-
|
167
|
-
struct STACKCHUNK* stack_chunk;
|
168
|
-
VALUE rb_stack_chunk = rb_stack_chunk_create(Qnil);
|
169
|
-
|
170
|
-
if (*stack_chunk_reference == 0) {
|
171
|
-
*stack_chunk_reference = (void*)get_stack_chunk_reference_from_context();
|
172
|
-
}
|
173
|
-
|
174
|
-
stack_chunk_reference_assign(*stack_chunk_reference, rb_stack_chunk);
|
175
|
-
Data_Get_Struct(rb_stack_chunk,void,stack_chunk);
|
176
|
-
|
177
|
-
*rb_stack_chunk_p = rb_stack_chunk;
|
178
|
-
|
179
|
-
return stack_chunk;
|
180
|
-
}
|
181
|
-
|
182
140
|
"
|
183
141
|
end
|
184
142
|
end
|
185
143
|
|
186
|
-
def on_block
|
187
|
-
yield
|
188
|
-
end
|
189
|
-
|
190
144
|
def to_c(tree)
|
191
145
|
return "Qnil" unless tree
|
192
146
|
send("to_c_" + tree[0].to_s, tree);
|
@@ -368,14 +322,10 @@ module FastRuby
|
|
368
322
|
VALUE ret = rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, 0);
|
369
323
|
|
370
324
|
// freeze all stacks
|
371
|
-
|
372
|
-
VALUE rb_stack_chunk_reference = rb_ivar_get(current_thread,#{intern_num :_fastruby_stack_chunk_reference});
|
325
|
+
struct FASTRUBYTHREADDATA* thread_data = rb_current_thread_data();
|
373
326
|
|
374
|
-
if (
|
375
|
-
|
376
|
-
Data_Get_Struct(rb_stack_chunk_reference, struct STACKCHUNKREFERENCE, stack_chunk_reference);
|
377
|
-
|
378
|
-
VALUE rb_stack_chunk = stack_chunk_reference_retrieve(stack_chunk_reference);
|
327
|
+
if (thread_data != 0) {
|
328
|
+
VALUE rb_stack_chunk = thread_data->rb_stack_chunk;
|
379
329
|
|
380
330
|
// add reference to stack chunk to lambda object
|
381
331
|
rb_ivar_set(ret,#{intern_num :_fastruby_stack_chunk},rb_stack_chunk);
|
@@ -408,39 +358,44 @@ module FastRuby
|
|
408
358
|
#{@locals_struct} *plocals = (void*)_plocals;
|
409
359
|
|
410
360
|
frame.plocals = plocals;
|
411
|
-
frame.stack_chunk = 0;
|
412
361
|
frame.parent_frame = 0;
|
413
362
|
frame.return_value = Qnil;
|
414
|
-
frame.target_frame = &frame;
|
415
|
-
frame.exception = Qnil;
|
416
363
|
frame.rescue = 0;
|
364
|
+
frame.targetted = 0;
|
365
|
+
frame.thread_data = rb_current_thread_data();
|
417
366
|
|
418
367
|
// create a fake parent frame representing the lambda method frame and a fake locals scope
|
419
368
|
VALUE old_call_frame = ((typeof(plocals))(pframe->plocals))->call_frame;
|
420
369
|
((typeof(plocals))(pframe->plocals))->call_frame = LONG2FIX(pframe);
|
421
370
|
|
422
|
-
|
423
|
-
|
424
|
-
if (
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
371
|
+
int aux = setjmp(frame.jmp);
|
372
|
+
if (aux != 0) {
|
373
|
+
if (aux == FASTRUBY_TAG_BREAK) {
|
374
|
+
return frame.return_value;
|
375
|
+
} else if (aux == FASTRUBY_TAG_NEXT) {
|
376
|
+
return pframe->thread_data->accumulator;
|
377
|
+
} else if (aux == FASTRUBY_TAG_REDO) {
|
378
|
+
// do nothing and let execute the block again
|
379
|
+
} else if (aux == FASTRUBY_TAG_RAISE) {
|
380
|
+
rb_funcall(((typeof(plocals))(pframe->plocals))->self, #{intern_num :raise}, 1, frame.thread_data->exception);
|
381
|
+
return Qnil;
|
382
|
+
} else {
|
383
|
+
if (aux == FASTRUBY_TAG_RETURN) {
|
384
|
+
if (((typeof(pframe))(FIX2LONG(plocals->pframe)))->targetted == 1) {
|
432
385
|
((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
|
433
|
-
return pframe->return_value;
|
386
|
+
return ((typeof(plocals))(pframe->plocals))->return_value;
|
434
387
|
} else {
|
435
388
|
rb_raise(rb_eLocalJumpError, \"unexpected return\");
|
436
389
|
}
|
390
|
+
} else {
|
391
|
+
rb_raise(rb_eLocalJumpError, \"unexpected return\");
|
437
392
|
}
|
438
|
-
}
|
439
|
-
((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
|
440
|
-
return frame.return_value;
|
441
|
-
}
|
442
393
|
|
394
|
+
((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
|
395
|
+
return frame.return_value;
|
443
396
|
|
397
|
+
}
|
398
|
+
}
|
444
399
|
|
445
400
|
#{str_arg_initialization}
|
446
401
|
#{str_impl}
|
@@ -461,49 +416,38 @@ module FastRuby
|
|
461
416
|
#{@locals_struct} *plocals = (void*)_plocals;
|
462
417
|
|
463
418
|
frame.plocals = plocals;
|
464
|
-
frame.stack_chunk = 0;
|
465
419
|
frame.parent_frame = 0;
|
466
420
|
frame.return_value = Qnil;
|
467
|
-
frame.target_frame = &frame;
|
468
|
-
frame.exception = Qnil;
|
469
421
|
frame.rescue = 0;
|
422
|
+
frame.targetted = 0;
|
423
|
+
frame.thread_data = rb_current_thread_data();
|
470
424
|
|
471
425
|
// create a fake parent frame representing the lambda method frame and a fake locals scope
|
472
426
|
VALUE old_call_frame = ((typeof(plocals))(pframe->plocals))->call_frame;
|
473
427
|
((typeof(plocals))(pframe->plocals))->call_frame = LONG2FIX(pframe);
|
474
428
|
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
if (plocals->
|
486
|
-
|
429
|
+
int aux = setjmp(frame.jmp);
|
430
|
+
if (aux != 0) {
|
431
|
+
if (aux == FASTRUBY_TAG_NEXT) {
|
432
|
+
return pframe->thread_data->accumulator;
|
433
|
+
} else if (aux == FASTRUBY_TAG_REDO) {
|
434
|
+
// do nothing and let execute the block again
|
435
|
+
} else if (aux == FASTRUBY_TAG_RAISE) {
|
436
|
+
rb_funcall(((typeof(plocals))(pframe->plocals))->self, #{intern_num :raise}, 1, frame.thread_data->exception);
|
437
|
+
return Qnil;
|
438
|
+
} else {
|
439
|
+
if (((typeof(pframe))(FIX2LONG(plocals->pframe)))->targetted == 1) {
|
440
|
+
|
441
|
+
if (plocals->active == Qfalse) {
|
442
|
+
rb_raise(rb_eLocalJumpError,\"return from proc-closure\");
|
443
|
+
} else {
|
444
|
+
((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
|
445
|
+
rb_jump_tag(aux);
|
446
|
+
}
|
487
447
|
} else {
|
488
|
-
(
|
489
|
-
VALUE ex = rb_funcall(
|
490
|
-
#{literal_value FastRuby::Context::UnwindFastrubyFrame},
|
491
|
-
#{intern_num :new},
|
492
|
-
3,
|
493
|
-
pframe->exception,
|
494
|
-
LONG2FIX(pframe->target_frame),
|
495
|
-
pframe->return_value
|
496
|
-
);
|
497
|
-
|
498
|
-
rb_funcall(plocals->self, #{intern_num :raise}, 1, ex);
|
448
|
+
rb_raise(rb_eLocalJumpError, \"unexpected return\");
|
499
449
|
}
|
500
|
-
} else {
|
501
|
-
rb_raise(rb_eLocalJumpError, \"unexpected return\");
|
502
450
|
}
|
503
|
-
}
|
504
|
-
}
|
505
|
-
|
506
|
-
rb_raise(rb_eLocalJumpError, \"break from proc-closure\");
|
507
451
|
}
|
508
452
|
|
509
453
|
#{str_arg_initialization}
|
@@ -527,32 +471,24 @@ module FastRuby
|
|
527
471
|
#{@locals_struct} *plocals = (void*)_plocals;
|
528
472
|
|
529
473
|
frame.plocals = plocals;
|
530
|
-
frame.stack_chunk = 0;
|
531
474
|
frame.parent_frame = 0;
|
532
475
|
frame.return_value = Qnil;
|
533
|
-
frame.target_frame = &frame;
|
534
|
-
frame.exception = Qnil;
|
535
476
|
frame.rescue = 0;
|
477
|
+
frame.targetted = 0;
|
478
|
+
frame.thread_data = rb_current_thread_data();
|
536
479
|
|
537
|
-
|
538
|
-
|
539
|
-
if (pframe->target_frame == (void*)-3) {
|
540
|
-
return pframe->return_value;
|
541
|
-
}
|
480
|
+
int aux = setjmp(frame.jmp);
|
481
|
+
if (aux != 0) {
|
542
482
|
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
);
|
551
|
-
|
552
|
-
rb_funcall(plocals->self, #{intern_num :raise}, 1, ex);
|
483
|
+
if (aux == FASTRUBY_TAG_NEXT) {
|
484
|
+
return pframe->thread_data->accumulator;
|
485
|
+
} else if (aux == FASTRUBY_TAG_REDO) {
|
486
|
+
// do nothing and let execute the block again
|
487
|
+
} else {
|
488
|
+
rb_jump_tag(aux);
|
489
|
+
return frame.return_value;
|
553
490
|
}
|
554
|
-
|
555
|
-
}
|
491
|
+
}
|
556
492
|
|
557
493
|
|
558
494
|
#{str_arg_initialization}
|
@@ -589,25 +525,24 @@ module FastRuby
|
|
589
525
|
|
590
526
|
frame.plocals = (void*)_locals;
|
591
527
|
frame.parent_frame = parent_frame;
|
592
|
-
frame.stack_chunk = parent_frame->stack_chunk;
|
593
528
|
frame.return_value = Qnil;
|
594
|
-
frame.target_frame = &frame;
|
595
|
-
frame.exception = Qnil;
|
596
529
|
frame.rescue = 0;
|
530
|
+
frame.targetted = 0;
|
531
|
+
frame.thread_data = parent_frame->thread_data;
|
532
|
+
if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
|
597
533
|
|
598
534
|
plocals = frame.plocals;
|
599
535
|
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
536
|
+
int aux = setjmp(frame.jmp);
|
537
|
+
if (aux != 0) {
|
538
|
+
if (pframe->targetted == 0) {
|
539
|
+
if (aux == FASTRUBY_TAG_NEXT) {
|
540
|
+
return pframe->thread_data->accumulator;
|
541
|
+
} else if (aux == FASTRUBY_TAG_REDO) {
|
542
|
+
// do nothing and let execute the block again
|
543
|
+
} else {
|
544
|
+
longjmp(((typeof(pframe))_parent_frame)->jmp,aux);
|
604
545
|
}
|
605
|
-
// raise exception
|
606
|
-
((typeof(pframe))_parent_frame)->exception = pframe->exception;
|
607
|
-
((typeof(pframe))_parent_frame)->target_frame = pframe->target_frame;
|
608
|
-
((typeof(pframe))_parent_frame)->return_value = pframe->return_value;
|
609
|
-
|
610
|
-
longjmp(((typeof(pframe))_parent_frame)->jmp,1);
|
611
546
|
}
|
612
547
|
|
613
548
|
}
|
@@ -629,29 +564,7 @@ module FastRuby
|
|
629
564
|
caller_code = nil
|
630
565
|
convention_global_name = add_global_name("int",0)
|
631
566
|
|
632
|
-
|
633
|
-
value_cast = ( ["VALUE"]*(call_tree[3].size) ).join(",") + ", VALUE, VALUE"
|
634
|
-
|
635
|
-
str_called_code_args = call_tree[3][1..-1].map{|subtree| to_c subtree}.join(",")
|
636
|
-
|
637
|
-
caller_code = proc { |name| "
|
638
|
-
static VALUE #{name}(VALUE param, VALUE pframe) {
|
639
|
-
#{@block_struct} block;
|
640
|
-
#{@locals_struct} *plocals = (void*)param;
|
641
|
-
|
642
|
-
block.block_function_address = (void*)#{anonymous_function(&block_code)};
|
643
|
-
block.block_function_param = (void*)param;
|
644
|
-
|
645
|
-
// call to #{call_tree[2]}
|
646
|
-
|
647
|
-
return ((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,call_tree,inference_complete,convention_global_name)})(#{str_recv}, (VALUE)&block, (VALUE)pframe, #{str_called_code_args});
|
648
|
-
}
|
649
|
-
"
|
650
|
-
}
|
651
|
-
|
652
|
-
else
|
653
|
-
caller_code = proc { |name| "
|
654
|
-
static VALUE #{name}(VALUE param, VALUE pframe) {
|
567
|
+
call_frame_struct_code = "
|
655
568
|
#{@block_struct} block;
|
656
569
|
#{@locals_struct} *plocals = (void*)param;
|
657
570
|
|
@@ -662,27 +575,52 @@ module FastRuby
|
|
662
575
|
#{@frame_struct} call_frame;
|
663
576
|
|
664
577
|
call_frame.parent_frame = (void*)pframe;
|
665
|
-
call_frame.target_frame = 0;
|
666
578
|
call_frame.plocals = plocals;
|
667
579
|
call_frame.return_value = Qnil;
|
668
|
-
call_frame.
|
669
|
-
call_frame.
|
580
|
+
call_frame.targetted = 0;
|
581
|
+
call_frame.thread_data = rb_current_thread_data();
|
670
582
|
|
671
583
|
VALUE old_call_frame = plocals->call_frame;
|
672
584
|
plocals->call_frame = LONG2FIX(&call_frame);
|
673
585
|
|
674
|
-
|
586
|
+
int aux = setjmp(call_frame.jmp);
|
587
|
+
if (aux != 0) {
|
675
588
|
#{@frame_struct}* pframe_ = (void*)pframe;
|
676
589
|
|
677
|
-
if (
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
590
|
+
if (aux == FASTRUBY_TAG_RETRY ) {
|
591
|
+
// do nothing and let the call execute again
|
592
|
+
} else {
|
593
|
+
if (call_frame.targetted == 0) {
|
594
|
+
longjmp(pframe_->jmp,aux);
|
595
|
+
}
|
682
596
|
|
683
|
-
|
684
|
-
|
597
|
+
plocals->call_frame = old_call_frame;
|
598
|
+
return call_frame.return_value;
|
599
|
+
}
|
685
600
|
}
|
601
|
+
"
|
602
|
+
|
603
|
+
if call_args_tree.size > 1
|
604
|
+
value_cast = ( ["VALUE"]*(call_tree[3].size) ).join(",") + ", VALUE, VALUE"
|
605
|
+
|
606
|
+
str_called_code_args = call_tree[3][1..-1].map{|subtree| to_c subtree}.join(",")
|
607
|
+
|
608
|
+
caller_code = proc { |name| "
|
609
|
+
static VALUE #{name}(VALUE param, VALUE pframe) {
|
610
|
+
// call to #{call_tree[2]}
|
611
|
+
#{call_frame_struct_code}
|
612
|
+
|
613
|
+
VALUE ret = ((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,call_tree,inference_complete,convention_global_name)})(#{str_recv}, (VALUE)&block, (VALUE)&call_frame, #{str_called_code_args});
|
614
|
+
plocals->call_frame = old_call_frame;
|
615
|
+
return ret;
|
616
|
+
}
|
617
|
+
"
|
618
|
+
}
|
619
|
+
|
620
|
+
else
|
621
|
+
caller_code = proc { |name| "
|
622
|
+
static VALUE #{name}(VALUE param, VALUE pframe) {
|
623
|
+
#{call_frame_struct_code}
|
686
624
|
|
687
625
|
// call to #{call_tree[2]}
|
688
626
|
VALUE ret = ((VALUE(*)(VALUE,VALUE,VALUE))#{encode_address(recvtype,signature,mname,call_tree,inference_complete,convention_global_name)})(#{str_recv}, (VALUE)&block, (VALUE)&call_frame);
|
@@ -746,24 +684,30 @@ module FastRuby
|
|
746
684
|
pframe = (typeof(pframe))&call_frame;
|
747
685
|
|
748
686
|
call_frame.parent_frame = (void*)pframe;
|
749
|
-
call_frame.target_frame = 0;
|
750
687
|
call_frame.plocals = plocals;
|
751
688
|
call_frame.return_value = Qnil;
|
752
|
-
call_frame.
|
753
|
-
call_frame.
|
689
|
+
call_frame.targetted = 0;
|
690
|
+
call_frame.thread_data = old_pframe->thread_data;
|
691
|
+
if (call_frame.thread_data == 0) call_frame.thread_data = rb_current_thread_data();
|
754
692
|
|
755
693
|
VALUE old_call_frame = plocals->call_frame;
|
756
694
|
plocals->call_frame = LONG2FIX(&call_frame);
|
757
695
|
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
old_pframe->
|
762
|
-
longjmp(old_pframe->jmp,1);
|
696
|
+
int aux = setjmp(call_frame.jmp);
|
697
|
+
if (aux != 0) {
|
698
|
+
if (call_frame.targetted == 0) {
|
699
|
+
longjmp(old_pframe->jmp,aux);
|
763
700
|
}
|
764
701
|
|
765
|
-
|
766
|
-
|
702
|
+
if (aux == FASTRUBY_TAG_BREAK) {
|
703
|
+
plocals->call_frame = old_call_frame;
|
704
|
+
return call_frame.return_value;
|
705
|
+
} else if (aux == FASTRUBY_TAG_RETRY ) {
|
706
|
+
// do nothing and let the call execute again
|
707
|
+
} else {
|
708
|
+
plocals->call_frame = old_call_frame;
|
709
|
+
return call_frame.return_value;
|
710
|
+
}
|
767
711
|
}
|
768
712
|
|
769
713
|
VALUE ret = #{inner_code};
|
@@ -847,16 +791,14 @@ module FastRuby
|
|
847
791
|
|
848
792
|
def to_c_return(tree)
|
849
793
|
inline_block "
|
850
|
-
pframe->target_frame = ((typeof(pframe))FIX2LONG(plocals->pframe));
|
851
794
|
plocals->return_value = #{to_c(tree[1])};
|
852
|
-
pframe->
|
853
|
-
longjmp(pframe->jmp,
|
795
|
+
((typeof(pframe))FIX2LONG(plocals->pframe))->targetted = 1;
|
796
|
+
longjmp(pframe->jmp, FASTRUBY_TAG_RETURN);
|
854
797
|
return Qnil;
|
855
798
|
"
|
856
799
|
end
|
857
800
|
|
858
801
|
def to_c_break(tree)
|
859
|
-
if @on_block
|
860
802
|
inline_block(
|
861
803
|
"
|
862
804
|
|
@@ -866,35 +808,63 @@ module FastRuby
|
|
866
808
|
target_frame_ = (void*)FIX2LONG(plocals->call_frame);
|
867
809
|
|
868
810
|
if (target_frame_ == 0) {
|
869
|
-
|
811
|
+
pframe->thread_data->exception = #{literal_value LocalJumpError.exception};
|
812
|
+
longjmp(pframe->jmp,FASTRUBY_TAG_RAISE);
|
813
|
+
return Qnil;
|
870
814
|
}
|
871
815
|
|
872
816
|
plocals->call_frame = LONG2FIX(0);
|
873
817
|
|
874
|
-
|
875
|
-
|
876
|
-
pframe->exception = Qnil;
|
877
|
-
longjmp(pframe->jmp,
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
818
|
+
target_frame_->return_value = value;
|
819
|
+
target_frame_->targetted = 1;
|
820
|
+
pframe->thread_data->exception = Qnil;
|
821
|
+
longjmp(pframe->jmp,FASTRUBY_TAG_BREAK);"
|
822
|
+
)
|
823
|
+
end
|
824
|
+
|
825
|
+
def to_c_retry(tree)
|
826
|
+
inline_block(
|
827
|
+
"
|
828
|
+
typeof(pframe) target_frame_;
|
829
|
+
target_frame_ = (void*)FIX2LONG(plocals->call_frame);
|
830
|
+
|
831
|
+
if (target_frame_ == 0) {
|
832
|
+
pframe->thread_data->exception = rb_funcall(rb_eLocalJumpError, #{intern_num :exception},0);
|
833
|
+
longjmp(pframe->jmp, FASTRUBY_TAG_RAISE);
|
884
834
|
return Qnil;
|
885
|
-
|
835
|
+
}
|
836
|
+
|
837
|
+
target_frame_->targetted = 1;
|
838
|
+
longjmp(pframe->jmp,FASTRUBY_TAG_RETRY);"
|
839
|
+
)
|
840
|
+
end
|
886
841
|
|
842
|
+
def to_c_redo(tree)
|
843
|
+
if @on_block
|
844
|
+
inline_block "
|
845
|
+
longjmp(pframe->jmp,FASTRUBY_TAG_REDO);
|
846
|
+
return Qnil;
|
847
|
+
"
|
848
|
+
else
|
849
|
+
inline_block "
|
850
|
+
pframe->thread_data->exception = #{literal_value LocalJumpError.exception};
|
851
|
+
longjmp(pframe->jmp,FASTRUBY_TAG_RAISE);
|
852
|
+
return Qnil;
|
853
|
+
"
|
887
854
|
end
|
888
855
|
end
|
889
856
|
|
890
857
|
def to_c_next(tree)
|
891
858
|
if @on_block
|
892
|
-
|
859
|
+
inline_block "
|
860
|
+
pframe->thread_data->accumulator = #{tree[1] ? to_c(tree[1]) : "Qnil"};
|
861
|
+
longjmp(pframe->jmp,FASTRUBY_TAG_NEXT);
|
862
|
+
return Qnil;
|
863
|
+
"
|
893
864
|
else
|
894
865
|
inline_block("
|
895
|
-
pframe->
|
896
|
-
pframe->
|
897
|
-
longjmp(pframe->jmp,1);
|
866
|
+
pframe->thread_data->exception = #{literal_value LocalJumpError.exception};
|
867
|
+
longjmp(pframe->jmp,FASTRUBY_TAG_RAISE);
|
898
868
|
return Qnil;
|
899
869
|
")
|
900
870
|
|
@@ -988,19 +958,19 @@ module FastRuby
|
|
988
958
|
|
989
959
|
code = tree[2..-2].map{|subtree|
|
990
960
|
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
961
|
+
# this subtree is a when
|
962
|
+
subtree[1][1..-1].map{|subsubtree|
|
963
|
+
c_calltree = s(:call, nil, :inline_c, s(:arglist, s(:str, tmpvarname), s(:false)))
|
964
|
+
calltree = s(:call, subsubtree, :===, s(:arglist, c_calltree))
|
995
965
|
"
|
996
966
|
if (RTEST(#{to_c_call(calltree, tmpvarname)})) {
|
997
967
|
return #{to_c(subtree[2])};
|
998
968
|
}
|
999
969
|
|
1000
970
|
"
|
1001
|
-
|
971
|
+
}.join("\n")
|
1002
972
|
|
1003
|
-
|
973
|
+
}.join("\n")
|
1004
974
|
|
1005
975
|
inline_block "
|
1006
976
|
|
@@ -1082,22 +1052,21 @@ module FastRuby
|
|
1082
1052
|
if (nd_type(body) == NODE_CFUNC) {
|
1083
1053
|
struct {
|
1084
1054
|
void* parent_frame;
|
1085
|
-
void* target_frame;
|
1086
1055
|
void* plocals;
|
1087
1056
|
jmp_buf jmp;
|
1088
1057
|
VALUE return_value;
|
1089
|
-
VALUE exception;
|
1090
1058
|
int rescue;
|
1091
1059
|
VALUE last_error;
|
1092
|
-
|
1060
|
+
VALUE next_recv;
|
1061
|
+
int targetted;
|
1062
|
+
struct FASTRUBYTHREADDATA* thread_data;
|
1093
1063
|
} frame;
|
1094
1064
|
|
1095
|
-
frame.stack_chunk = 0;
|
1096
|
-
frame.target_frame = 0;
|
1097
1065
|
frame.parent_frame = 0;
|
1098
1066
|
frame.rescue = 0;
|
1099
|
-
frame.exception = Qnil;
|
1100
1067
|
frame.return_value = Qnil;
|
1068
|
+
frame.thread_data = rb_current_thread_data();
|
1069
|
+
frame.targetted = 0;
|
1101
1070
|
|
1102
1071
|
int argc = body->nd_argc;
|
1103
1072
|
|
@@ -1117,21 +1086,12 @@ module FastRuby
|
|
1117
1086
|
|
1118
1087
|
int aux = setjmp(frame.jmp);
|
1119
1088
|
if (aux != 0) {
|
1120
|
-
if (
|
1121
|
-
rb_funcall(self, #{intern_num :raise}, 1, frame.exception);
|
1089
|
+
if (aux == FASTRUBY_TAG_RAISE) {
|
1090
|
+
rb_funcall(self, #{intern_num :raise}, 1, frame.thread_data->exception);
|
1122
1091
|
}
|
1123
1092
|
|
1124
|
-
if (frame.
|
1125
|
-
|
1126
|
-
#{literal_value FastRuby::Context::UnwindFastrubyFrame},
|
1127
|
-
#{intern_num :new},
|
1128
|
-
3,
|
1129
|
-
frame.exception,
|
1130
|
-
LONG2FIX(frame.target_frame),
|
1131
|
-
frame.return_value
|
1132
|
-
);
|
1133
|
-
|
1134
|
-
rb_funcall(self, #{intern_num :raise}, 1, ex);
|
1093
|
+
if (frame.targetted == 0) {
|
1094
|
+
rb_jump_tag(aux);
|
1135
1095
|
}
|
1136
1096
|
|
1137
1097
|
return Qnil;
|
@@ -1299,13 +1259,12 @@ module FastRuby
|
|
1299
1259
|
void* block_address = 0;
|
1300
1260
|
VALUE block_param = Qnil;
|
1301
1261
|
|
1302
|
-
frame.stack_chunk = 0;
|
1303
1262
|
frame.plocals = 0;
|
1304
1263
|
frame.parent_frame = 0;
|
1305
1264
|
frame.return_value = Qnil;
|
1306
|
-
frame.target_frame = &frame;
|
1307
|
-
frame.exception = Qnil;
|
1308
1265
|
frame.rescue = 0;
|
1266
|
+
frame.targetted = 0;
|
1267
|
+
frame.thread_data = rb_current_thread_data();
|
1309
1268
|
|
1310
1269
|
if (rb_block_given_p()) {
|
1311
1270
|
block_address = #{
|
@@ -1321,7 +1280,7 @@ module FastRuby
|
|
1321
1280
|
|
1322
1281
|
int aux = setjmp(frame.jmp);
|
1323
1282
|
if (aux != 0) {
|
1324
|
-
rb_funcall(self, #{intern_num :raise}, 1, frame.exception);
|
1283
|
+
rb_funcall(self, #{intern_num :raise}, 1, frame.thread_data->exception);
|
1325
1284
|
}
|
1326
1285
|
|
1327
1286
|
|
@@ -1389,35 +1348,38 @@ module FastRuby
|
|
1389
1348
|
#{@frame_struct} frame;
|
1390
1349
|
#{@frame_struct} *pframe;
|
1391
1350
|
|
1392
|
-
frame.stack_chunk = 0;
|
1393
1351
|
frame.parent_frame = 0;
|
1394
1352
|
frame.return_value = Qnil;
|
1395
|
-
frame.target_frame = &frame;
|
1396
|
-
frame.exception = Qnil;
|
1397
1353
|
frame.rescue = 0;
|
1354
|
+
frame.targetted = 0;
|
1355
|
+
frame.thread_data = rb_current_thread_data();
|
1398
1356
|
|
1399
1357
|
|
1400
1358
|
int stack_chunk_instantiated = 0;
|
1401
1359
|
VALUE rb_previous_stack_chunk = Qnil;
|
1402
|
-
VALUE
|
1403
|
-
|
1404
|
-
struct STACKCHUNKREFERENCE* stack_chunk_reference = 0;
|
1360
|
+
VALUE rb_stack_chunk = frame.thread_data->rb_stack_chunk;
|
1361
|
+
struct STACKCHUNK* stack_chunk = 0;
|
1405
1362
|
|
1406
|
-
if (
|
1407
|
-
|
1363
|
+
if (rb_stack_chunk != Qnil) {
|
1364
|
+
Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
|
1408
1365
|
}
|
1409
1366
|
|
1410
|
-
if (
|
1367
|
+
if (stack_chunk == 0 || (stack_chunk == 0 ? 0 : stack_chunk_frozen(stack_chunk)) ) {
|
1411
1368
|
rb_previous_stack_chunk = rb_stack_chunk;
|
1412
1369
|
rb_gc_register_address(&rb_stack_chunk);
|
1413
1370
|
stack_chunk_instantiated = 1;
|
1414
1371
|
|
1415
|
-
|
1372
|
+
rb_stack_chunk = rb_stack_chunk_create(Qnil);
|
1373
|
+
frame.thread_data->rb_stack_chunk = rb_stack_chunk;
|
1374
|
+
|
1375
|
+
rb_ivar_set(rb_stack_chunk, #{intern_num :_parent_stack_chunk}, rb_previous_stack_chunk);
|
1376
|
+
|
1377
|
+
Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
|
1416
1378
|
}
|
1417
1379
|
|
1418
|
-
int previous_stack_position = stack_chunk_get_current_position(
|
1380
|
+
int previous_stack_position = stack_chunk_get_current_position(stack_chunk);
|
1419
1381
|
|
1420
|
-
plocals = (typeof(plocals))stack_chunk_alloc(
|
1382
|
+
plocals = (typeof(plocals))stack_chunk_alloc(stack_chunk ,sizeof(typeof(*plocals))/sizeof(void*));
|
1421
1383
|
plocals->active = Qtrue;
|
1422
1384
|
plocals->pframe = LONG2FIX(&frame);
|
1423
1385
|
frame.plocals = plocals;
|
@@ -1428,17 +1390,11 @@ module FastRuby
|
|
1428
1390
|
|
1429
1391
|
int aux = setjmp(pframe->jmp);
|
1430
1392
|
if (aux != 0) {
|
1431
|
-
stack_chunk_set_current_position(
|
1393
|
+
stack_chunk_set_current_position(stack_chunk, previous_stack_position);
|
1432
1394
|
|
1433
1395
|
if (stack_chunk_instantiated) {
|
1434
1396
|
rb_gc_unregister_address(&rb_stack_chunk);
|
1435
|
-
|
1436
|
-
}
|
1437
|
-
|
1438
|
-
if (pframe->target_frame != pframe) {
|
1439
|
-
// raise exception
|
1440
|
-
plocals->active = Qfalse;
|
1441
|
-
return Qnil;
|
1397
|
+
frame.thread_data->rb_stack_chunk = rb_previous_stack_chunk;
|
1442
1398
|
}
|
1443
1399
|
|
1444
1400
|
plocals->active = Qfalse;
|
@@ -1456,11 +1412,11 @@ module FastRuby
|
|
1456
1412
|
plocals->call_frame = LONG2FIX(0);
|
1457
1413
|
|
1458
1414
|
VALUE ret = #{to_c impl_tree};
|
1459
|
-
stack_chunk_set_current_position(
|
1415
|
+
stack_chunk_set_current_position(stack_chunk, previous_stack_position);
|
1460
1416
|
|
1461
1417
|
if (stack_chunk_instantiated) {
|
1462
1418
|
rb_gc_unregister_address(&rb_stack_chunk);
|
1463
|
-
|
1419
|
+
frame.thread_data->rb_stack_chunk = rb_previous_stack_chunk;
|
1464
1420
|
}
|
1465
1421
|
|
1466
1422
|
plocals->active = Qfalse;
|
@@ -1486,36 +1442,40 @@ module FastRuby
|
|
1486
1442
|
#{@frame_struct} *pframe;
|
1487
1443
|
|
1488
1444
|
frame.parent_frame = (void*)_parent_frame;
|
1489
|
-
frame.stack_chunk = ((typeof(pframe))_parent_frame)->stack_chunk;
|
1490
1445
|
frame.return_value = Qnil;
|
1491
|
-
frame.target_frame = &frame;
|
1492
|
-
frame.exception = Qnil;
|
1493
1446
|
frame.rescue = 0;
|
1447
|
+
frame.targetted = 0;
|
1448
|
+
frame.thread_data = ((typeof(pframe))_parent_frame)->thread_data;
|
1449
|
+
if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
|
1494
1450
|
|
1495
1451
|
int stack_chunk_instantiated = 0;
|
1496
1452
|
VALUE rb_previous_stack_chunk = Qnil;
|
1497
|
-
VALUE
|
1498
|
-
|
1499
|
-
struct STACKCHUNKREFERENCE* stack_chunk_reference = 0;
|
1453
|
+
VALUE rb_stack_chunk = frame.thread_data->rb_stack_chunk;
|
1454
|
+
struct STACKCHUNK* stack_chunk = 0;
|
1500
1455
|
|
1501
|
-
if (
|
1502
|
-
|
1456
|
+
if (rb_stack_chunk != Qnil) {
|
1457
|
+
Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
|
1503
1458
|
}
|
1504
1459
|
|
1505
|
-
if (
|
1460
|
+
if (stack_chunk == 0 || (stack_chunk == 0 ? 0 : stack_chunk_frozen(stack_chunk)) ) {
|
1506
1461
|
rb_previous_stack_chunk = rb_stack_chunk;
|
1507
1462
|
rb_gc_register_address(&rb_stack_chunk);
|
1508
1463
|
stack_chunk_instantiated = 1;
|
1509
1464
|
|
1510
|
-
|
1465
|
+
rb_stack_chunk = rb_stack_chunk_create(Qnil);
|
1466
|
+
frame.thread_data->rb_stack_chunk = rb_stack_chunk;
|
1467
|
+
|
1468
|
+
rb_ivar_set(rb_stack_chunk, #{intern_num :_parent_stack_chunk}, rb_previous_stack_chunk);
|
1469
|
+
|
1470
|
+
Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
|
1511
1471
|
}
|
1512
1472
|
|
1513
1473
|
|
1514
1474
|
#{@locals_struct} *plocals;
|
1515
1475
|
|
1516
|
-
int previous_stack_position = stack_chunk_get_current_position(
|
1476
|
+
int previous_stack_position = stack_chunk_get_current_position(stack_chunk);
|
1517
1477
|
|
1518
|
-
plocals = (typeof(plocals))stack_chunk_alloc(
|
1478
|
+
plocals = (typeof(plocals))stack_chunk_alloc(stack_chunk ,sizeof(typeof(*plocals))/sizeof(void*));
|
1519
1479
|
frame.plocals = plocals;
|
1520
1480
|
plocals->active = Qtrue;
|
1521
1481
|
plocals->pframe = LONG2FIX(&frame);
|
@@ -1530,20 +1490,15 @@ module FastRuby
|
|
1530
1490
|
if (aux != 0) {
|
1531
1491
|
plocals->active = Qfalse;
|
1532
1492
|
|
1533
|
-
stack_chunk_set_current_position(
|
1493
|
+
stack_chunk_set_current_position(stack_chunk, previous_stack_position);
|
1534
1494
|
|
1535
1495
|
if (stack_chunk_instantiated) {
|
1536
1496
|
rb_gc_unregister_address(&rb_stack_chunk);
|
1537
|
-
|
1497
|
+
frame.thread_data->rb_stack_chunk = rb_previous_stack_chunk;
|
1538
1498
|
}
|
1539
1499
|
|
1540
|
-
if (pframe->
|
1541
|
-
|
1542
|
-
((typeof(pframe))_parent_frame)->exception = pframe->exception;
|
1543
|
-
((typeof(pframe))_parent_frame)->target_frame = pframe->target_frame;
|
1544
|
-
((typeof(pframe))_parent_frame)->return_value = pframe->return_value;
|
1545
|
-
|
1546
|
-
longjmp(((typeof(pframe))_parent_frame)->jmp,1);
|
1500
|
+
if (pframe->targetted == 0) {
|
1501
|
+
longjmp(((typeof(pframe))_parent_frame)->jmp,aux);
|
1547
1502
|
}
|
1548
1503
|
|
1549
1504
|
return plocals->return_value;
|
@@ -1565,11 +1520,11 @@ module FastRuby
|
|
1565
1520
|
}
|
1566
1521
|
|
1567
1522
|
VALUE __ret = #{to_c impl_tree};
|
1568
|
-
stack_chunk_set_current_position(
|
1523
|
+
stack_chunk_set_current_position(stack_chunk, previous_stack_position);
|
1569
1524
|
|
1570
1525
|
if (stack_chunk_instantiated) {
|
1571
1526
|
rb_gc_unregister_address(&rb_stack_chunk);
|
1572
|
-
|
1527
|
+
frame.thread_data->rb_stack_chunk = rb_previous_stack_chunk;
|
1573
1528
|
}
|
1574
1529
|
|
1575
1530
|
plocals->active = Qfalse;
|
@@ -1711,14 +1666,25 @@ module FastRuby
|
|
1711
1666
|
resbody_tree = tree[2]
|
1712
1667
|
else_tree = tree[3]
|
1713
1668
|
|
1714
|
-
|
1715
|
-
|
1716
|
-
|
1717
|
-
|
1718
|
-
|
1719
|
-
|
1669
|
+
trapcode = "rb_eException";
|
1670
|
+
if resbody_tree[1][1]
|
1671
|
+
trapcode = to_c(resbody_tree[1][1])
|
1672
|
+
end
|
1673
|
+
|
1674
|
+
frame_call(
|
1675
|
+
frame(to_c(tree[1])+";","
|
1676
|
+
if (aux == FASTRUBY_TAG_RAISE) {
|
1677
|
+
if (rb_obj_is_kind_of(frame.thread_data->exception,#{trapcode}) == Qtrue)
|
1678
|
+
{
|
1679
|
+
// trap exception
|
1680
|
+
frame.targetted = 1;
|
1681
|
+
|
1682
|
+
#{to_c(resbody_tree[2])};
|
1683
|
+
}
|
1720
1684
|
}
|
1721
1685
|
", else_tree ? to_c(else_tree) : nil, 1)
|
1686
|
+
|
1687
|
+
)
|
1722
1688
|
end
|
1723
1689
|
end
|
1724
1690
|
|
@@ -1746,9 +1712,8 @@ module FastRuby
|
|
1746
1712
|
args = tree[3]
|
1747
1713
|
|
1748
1714
|
return inline_block("
|
1749
|
-
pframe->
|
1750
|
-
pframe->
|
1751
|
-
longjmp(pframe->jmp, 1);
|
1715
|
+
pframe->thread_data->exception = rb_funcall(#{to_c args[1]}, #{intern_num :exception},0);
|
1716
|
+
longjmp(pframe->jmp, FASTRUBY_TAG_RAISE);
|
1752
1717
|
return Qnil;
|
1753
1718
|
")
|
1754
1719
|
end
|
@@ -1874,34 +1839,37 @@ module FastRuby
|
|
1874
1839
|
typeof(&frame) pframe = &frame;
|
1875
1840
|
#{@locals_struct} *plocals;
|
1876
1841
|
|
1877
|
-
frame.stack_chunk = 0;
|
1878
1842
|
frame.parent_frame = 0;
|
1879
1843
|
frame.return_value = Qnil;
|
1880
|
-
frame.target_frame = &frame;
|
1881
|
-
frame.exception = Qnil;
|
1882
1844
|
frame.rescue = 0;
|
1845
|
+
frame.targetted = 0;
|
1846
|
+
frame.thread_data = rb_current_thread_data();
|
1883
1847
|
|
1884
1848
|
int stack_chunk_instantiated = 0;
|
1885
1849
|
VALUE rb_previous_stack_chunk = Qnil;
|
1886
|
-
VALUE
|
1887
|
-
|
1888
|
-
struct STACKCHUNKREFERENCE* stack_chunk_reference = 0;
|
1850
|
+
VALUE rb_stack_chunk = frame.thread_data->rb_stack_chunk;
|
1851
|
+
struct STACKCHUNK* stack_chunk = 0;
|
1889
1852
|
|
1890
|
-
if (
|
1891
|
-
|
1853
|
+
if (rb_stack_chunk != Qnil) {
|
1854
|
+
Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
|
1892
1855
|
}
|
1893
1856
|
|
1894
|
-
if (
|
1857
|
+
if (stack_chunk == 0 || (stack_chunk == 0 ? 0 : stack_chunk_frozen(stack_chunk)) ) {
|
1895
1858
|
rb_previous_stack_chunk = rb_stack_chunk;
|
1896
1859
|
rb_gc_register_address(&rb_stack_chunk);
|
1897
1860
|
stack_chunk_instantiated = 1;
|
1898
1861
|
|
1899
|
-
|
1862
|
+
rb_stack_chunk = rb_stack_chunk_create(Qnil);
|
1863
|
+
frame.thread_data->rb_stack_chunk = rb_stack_chunk;
|
1864
|
+
|
1865
|
+
rb_ivar_set(rb_stack_chunk, #{intern_num :_parent_stack_chunk}, rb_previous_stack_chunk);
|
1866
|
+
|
1867
|
+
Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
|
1900
1868
|
}
|
1901
1869
|
|
1902
|
-
int previous_stack_position = stack_chunk_get_current_position(
|
1870
|
+
int previous_stack_position = stack_chunk_get_current_position(stack_chunk);
|
1903
1871
|
|
1904
|
-
plocals = (typeof(plocals))stack_chunk_alloc(
|
1872
|
+
plocals = (typeof(plocals))stack_chunk_alloc(stack_chunk ,sizeof(typeof(*plocals))/sizeof(void*));
|
1905
1873
|
|
1906
1874
|
frame.plocals = plocals;
|
1907
1875
|
plocals->active = Qtrue;
|
@@ -1910,11 +1878,11 @@ module FastRuby
|
|
1910
1878
|
|
1911
1879
|
#{to_c tree};
|
1912
1880
|
|
1913
|
-
stack_chunk_set_current_position(
|
1881
|
+
stack_chunk_set_current_position(stack_chunk, previous_stack_position);
|
1914
1882
|
|
1915
1883
|
if (stack_chunk_instantiated) {
|
1916
1884
|
rb_gc_unregister_address(&rb_stack_chunk);
|
1917
|
-
|
1885
|
+
frame.thread_data->rb_stack_chunk = rb_previous_stack_chunk;
|
1918
1886
|
}
|
1919
1887
|
|
1920
1888
|
plocals->active = Qfalse;
|
@@ -1978,6 +1946,13 @@ module FastRuby
|
|
1978
1946
|
end
|
1979
1947
|
end
|
1980
1948
|
|
1949
|
+
def to_c_for(tree)
|
1950
|
+
alter_tree = tree.dup
|
1951
|
+
alter_tree[0] = :iter
|
1952
|
+
alter_tree[1] = [:call, alter_tree[1], :each, [:arglist]]
|
1953
|
+
to_c alter_tree
|
1954
|
+
end
|
1955
|
+
|
1981
1956
|
def to_c_while(tree)
|
1982
1957
|
inline_block("
|
1983
1958
|
while (#{to_c tree[1]}) {
|
@@ -2101,36 +2076,6 @@ module FastRuby
|
|
2101
2076
|
end
|
2102
2077
|
|
2103
2078
|
def protected_block(inner_code, always_rescue = false,repass_var = nil, nolocals = false)
|
2104
|
-
wrapper_code = "
|
2105
|
-
if (pframe->last_error != Qnil) {
|
2106
|
-
if (CLASS_OF(pframe->last_error)==#{literal_value FastRuby::Context::UnwindFastrubyFrame}) {
|
2107
|
-
#{@frame_struct} *pframe = (void*)param;
|
2108
|
-
|
2109
|
-
pframe->target_frame = (void*)FIX2LONG(rb_ivar_get(pframe->last_error, #{intern_num :@target_frame}));
|
2110
|
-
pframe->exception = rb_ivar_get(pframe->last_error, #{intern_num :@ex});
|
2111
|
-
pframe->return_value = rb_ivar_get(pframe->last_error, #{intern_num :@return_value});
|
2112
|
-
|
2113
|
-
longjmp(pframe->jmp, 1);
|
2114
|
-
return Qnil;
|
2115
|
-
|
2116
|
-
} else {
|
2117
|
-
|
2118
|
-
// raise emulation
|
2119
|
-
#{@frame_struct} *pframe = (void*)param;
|
2120
|
-
pframe->target_frame = (void*)-1;
|
2121
|
-
pframe->exception = pframe->last_error;
|
2122
|
-
longjmp(pframe->jmp, 1);
|
2123
|
-
return Qnil;
|
2124
|
-
}
|
2125
|
-
|
2126
|
-
} else {
|
2127
|
-
if (pframe->target_frame != pframe) {
|
2128
|
-
longjmp(pframe->jmp, 1);
|
2129
|
-
}
|
2130
|
-
}
|
2131
|
-
"
|
2132
|
-
|
2133
|
-
|
2134
2079
|
body = nil
|
2135
2080
|
rescue_args = nil
|
2136
2081
|
if repass_var
|
@@ -2143,12 +2088,12 @@ module FastRuby
|
|
2143
2088
|
typeof(frame)* parent_frame = ((typeof(pframe))((void**)param)[0]);
|
2144
2089
|
|
2145
2090
|
frame.parent_frame = 0;
|
2146
|
-
frame.target_frame = 0;
|
2147
2091
|
frame.return_value = Qnil;
|
2148
|
-
frame.exception = Qnil;
|
2149
2092
|
frame.rescue = 0;
|
2150
2093
|
frame.last_error = Qnil;
|
2151
|
-
frame.
|
2094
|
+
frame.targetted = 0;
|
2095
|
+
frame.thread_data = parent_frame->thread_data;
|
2096
|
+
if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
|
2152
2097
|
|
2153
2098
|
pframe = &frame;
|
2154
2099
|
|
@@ -2158,12 +2103,14 @@ module FastRuby
|
|
2158
2103
|
"
|
2159
2104
|
}
|
2160
2105
|
|
2161
|
-
|
2162
|
-
|
2163
|
-
parent_frame->exception = frame.exception;
|
2164
|
-
parent_frame->return_value = frame.return_value;
|
2106
|
+
int aux = setjmp(frame.jmp);
|
2107
|
+
if (aux != 0) {
|
2165
2108
|
|
2166
|
-
|
2109
|
+
if (frame.targetted == 1) {
|
2110
|
+
return frame.return_value;
|
2111
|
+
} else {
|
2112
|
+
rb_jump_tag(aux);
|
2113
|
+
}
|
2167
2114
|
}
|
2168
2115
|
|
2169
2116
|
VALUE #{repass_var} = (VALUE)((void**)param)[1];
|
@@ -2184,12 +2131,12 @@ module FastRuby
|
|
2184
2131
|
typeof(frame)* parent_frame = (typeof(pframe))param;
|
2185
2132
|
|
2186
2133
|
frame.parent_frame = 0;
|
2187
|
-
frame.target_frame = 0;
|
2188
2134
|
frame.return_value = Qnil;
|
2189
|
-
frame.exception = Qnil;
|
2190
2135
|
frame.rescue = 0;
|
2191
2136
|
frame.last_error = Qnil;
|
2192
|
-
frame.
|
2137
|
+
frame.targetted = 0;
|
2138
|
+
frame.thread_data = parent_frame->thread_data;
|
2139
|
+
if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
|
2193
2140
|
|
2194
2141
|
pframe = &frame;
|
2195
2142
|
|
@@ -2199,12 +2146,14 @@ module FastRuby
|
|
2199
2146
|
"
|
2200
2147
|
}
|
2201
2148
|
|
2202
|
-
|
2203
|
-
|
2204
|
-
parent_frame->exception = frame.exception;
|
2205
|
-
parent_frame->return_value = frame.return_value;
|
2149
|
+
int aux = setjmp(frame.jmp);
|
2150
|
+
if (aux != 0) {
|
2206
2151
|
|
2207
|
-
|
2152
|
+
if (frame.targetted == 1) {
|
2153
|
+
return frame.return_value;
|
2154
|
+
} else {
|
2155
|
+
rb_jump_tag(aux);
|
2156
|
+
}
|
2208
2157
|
}
|
2209
2158
|
|
2210
2159
|
return #{inner_code};
|
@@ -2215,18 +2164,30 @@ module FastRuby
|
|
2215
2164
|
rescue_args = "(VALUE)pframe"
|
2216
2165
|
end
|
2217
2166
|
|
2218
|
-
|
2219
|
-
|
2220
|
-
|
2221
|
-
|
2167
|
+
wrapper_code = " if (state != 0) {
|
2168
|
+
if (state < 0x80) {
|
2169
|
+
|
2170
|
+
if (state == TAG_RAISE) {
|
2171
|
+
// raise emulation
|
2172
|
+
pframe->thread_data->exception = rb_eval_string(\"$!\");
|
2173
|
+
longjmp(pframe->jmp, FASTRUBY_TAG_RAISE);
|
2174
|
+
return Qnil;
|
2175
|
+
} else {
|
2176
|
+
rb_jump_tag(state);
|
2177
|
+
}
|
2178
|
+
} else {
|
2179
|
+
longjmp(pframe->jmp, state);
|
2222
2180
|
}
|
2223
|
-
|
2224
|
-
|
2181
|
+
|
2182
|
+
}
|
2183
|
+
"
|
2184
|
+
|
2185
|
+
rescue_code = "rb_protect(#{body},#{rescue_args},&state)"
|
2225
2186
|
|
2226
2187
|
if always_rescue
|
2227
2188
|
inline_block "
|
2189
|
+
int state;
|
2228
2190
|
pframe->last_error = Qnil;
|
2229
|
-
pframe->target_frame = pframe;
|
2230
2191
|
VALUE result = #{rescue_code};
|
2231
2192
|
|
2232
2193
|
#{wrapper_code}
|
@@ -2236,23 +2197,21 @@ module FastRuby
|
|
2236
2197
|
else
|
2237
2198
|
inline_block "
|
2238
2199
|
VALUE result;
|
2200
|
+
int state;
|
2239
2201
|
pframe->last_error = Qnil;
|
2240
2202
|
|
2241
2203
|
if (pframe->rescue) {
|
2242
2204
|
result = #{rescue_code};
|
2205
|
+
#{wrapper_code}
|
2243
2206
|
} else {
|
2244
2207
|
return #{inner_code};
|
2245
2208
|
}
|
2246
2209
|
|
2247
|
-
#{wrapper_code}
|
2248
|
-
|
2249
2210
|
return result;
|
2250
2211
|
", repass_var, nolocals
|
2251
2212
|
end
|
2252
|
-
|
2253
2213
|
end
|
2254
2214
|
|
2255
|
-
|
2256
2215
|
def func_frame
|
2257
2216
|
"
|
2258
2217
|
#{@locals_struct} *plocals = malloc(sizeof(typeof(*plocals)));
|
@@ -2261,11 +2220,11 @@ module FastRuby
|
|
2261
2220
|
|
2262
2221
|
frame.plocals = plocals;
|
2263
2222
|
frame.parent_frame = (void*)_parent_frame;
|
2264
|
-
frame.stack_chunk = ((typeof(pframe))_parent_frame)->stack_chunk;
|
2265
2223
|
frame.return_value = Qnil;
|
2266
|
-
frame.target_frame = &frame;
|
2267
|
-
frame.exception = Qnil;
|
2268
2224
|
frame.rescue = 0;
|
2225
|
+
frame.targetted = 0;
|
2226
|
+
frame.thread_data = ((typeof(pframe))_parent_frame)->thread_data;
|
2227
|
+
if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
|
2269
2228
|
|
2270
2229
|
plocals->pframe = LONG2FIX(&frame);
|
2271
2230
|
|
@@ -2277,12 +2236,8 @@ module FastRuby
|
|
2277
2236
|
int aux = setjmp(pframe->jmp);
|
2278
2237
|
if (aux != 0) {
|
2279
2238
|
|
2280
|
-
if (pframe->
|
2281
|
-
|
2282
|
-
((typeof(pframe))_parent_frame)->exception = pframe->exception;
|
2283
|
-
((typeof(pframe))_parent_frame)->target_frame = pframe->target_frame;
|
2284
|
-
((typeof(pframe))_parent_frame)->return_value = pframe->return_value;
|
2285
|
-
longjmp(((typeof(pframe))_parent_frame)->jmp,1);
|
2239
|
+
if (pframe->targetted == 0) {
|
2240
|
+
longjmp(((typeof(pframe))_parent_frame)->jmp,aux);
|
2286
2241
|
}
|
2287
2242
|
|
2288
2243
|
return plocals->return_value;
|
@@ -2547,12 +2502,12 @@ module FastRuby
|
|
2547
2502
|
|
2548
2503
|
parent_frame = (void*)param;
|
2549
2504
|
|
2550
|
-
frame.stack_chunk = parent_frame->stack_chunk;
|
2551
2505
|
frame.parent_frame = (void*)param;
|
2552
2506
|
frame.plocals = parent_frame->plocals;
|
2553
|
-
frame.target_frame = &frame;
|
2554
|
-
frame.exception = Qnil;
|
2555
2507
|
frame.rescue = #{rescued ? rescued : "parent_frame->rescue"};
|
2508
|
+
frame.targetted = 0;
|
2509
|
+
frame.thread_data = parent_frame->thread_data;
|
2510
|
+
if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
|
2556
2511
|
|
2557
2512
|
plocals = frame.plocals;
|
2558
2513
|
pframe = &frame;
|
@@ -2567,12 +2522,8 @@ module FastRuby
|
|
2567
2522
|
|
2568
2523
|
#{jmp_code};
|
2569
2524
|
|
2570
|
-
if (original_frame->
|
2571
|
-
pframe->
|
2572
|
-
pframe->target_frame = original_frame->target_frame;
|
2573
|
-
pframe->return_value = original_frame->return_value;
|
2574
|
-
|
2575
|
-
longjmp(pframe->jmp,1);
|
2525
|
+
if (original_frame->targetted == 0) {
|
2526
|
+
longjmp(pframe->jmp,aux);
|
2576
2527
|
}
|
2577
2528
|
|
2578
2529
|
return last_expression;
|