fastruby 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- VALUE current_thread = rb_thread_current();
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 (rb_stack_chunk_reference != Qnil) {
375
- struct STACKCHUNKREFERENCE* stack_chunk_reference;
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
- if (setjmp(frame.jmp) != 0) {
423
-
424
- if (pframe->target_frame != pframe) {
425
- if (pframe->target_frame == (void*)-3) {
426
- return pframe->return_value;
427
- } else if (pframe->target_frame == (void*)-1) {
428
- rb_funcall(((typeof(plocals))(pframe->plocals))->self, #{intern_num :raise}, 1, frame.exception);
429
- return Qnil;
430
- } else {
431
- if (pframe->target_frame == (void*)FIX2LONG(plocals->pframe)) {
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
- if (setjmp(frame.jmp) != 0) {
476
- if (pframe->target_frame != pframe) {
477
- if (pframe->target_frame == (void*)-3) {
478
- return pframe->return_value;
479
- } else if (pframe->target_frame == (void*)-1) {
480
- rb_funcall(((typeof(plocals))(pframe->plocals))->self, #{intern_num :raise}, 1, frame.exception);
481
- return Qnil;
482
- } else {
483
- if (pframe->target_frame == (void*)FIX2LONG(plocals->pframe)) {
484
-
485
- if (plocals->active == Qfalse) {
486
- rb_raise(rb_eLocalJumpError,\"return from proc-closure\");
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
- ((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
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
- if (setjmp(frame.jmp) != 0) {
538
- if (pframe->target_frame != pframe) {
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
- VALUE ex = rb_funcall(
544
- #{literal_value FastRuby::Context::UnwindFastrubyFrame},
545
- #{intern_num :new},
546
- 3,
547
- pframe->exception,
548
- LONG2FIX(pframe->target_frame),
549
- pframe->return_value
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
- return frame.return_value;
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
- if (setjmp(frame.jmp) != 0) {
601
- if (pframe->target_frame != pframe) {
602
- if (pframe->target_frame == (void*)-3) {
603
- return pframe->return_value;
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
- if call_args_tree.size > 1
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.exception = Qnil;
669
- call_frame.stack_chunk = ((typeof(&call_frame))pframe)->stack_chunk;
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
- if (setjmp(call_frame.jmp) != 0) {
586
+ int aux = setjmp(call_frame.jmp);
587
+ if (aux != 0) {
675
588
  #{@frame_struct}* pframe_ = (void*)pframe;
676
589
 
677
- if (call_frame.target_frame != &call_frame) {
678
- pframe_->target_frame = call_frame.target_frame;
679
- pframe_->exception = call_frame.exception;
680
- longjmp(pframe_->jmp,1);
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
- plocals->call_frame = old_call_frame;
684
- return call_frame.return_value;
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.exception = Qnil;
753
- call_frame.stack_chunk = ((typeof(&call_frame))pframe)->stack_chunk;
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
- if (setjmp(call_frame.jmp) != 0) {
759
- if (call_frame.target_frame != &call_frame) {
760
- old_pframe->target_frame = call_frame.target_frame;
761
- old_pframe->exception = call_frame.exception;
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
- plocals->call_frame = old_call_frame;
766
- return call_frame.return_value;
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->return_value = plocals->return_value;
853
- longjmp(pframe->jmp, 1);
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
- rb_raise(rb_eLocalJumpError, \"illegal break\");
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
- pframe->target_frame = target_frame_;
875
- pframe->return_value = value;
876
- pframe->exception = Qnil;
877
- longjmp(pframe->jmp,1);"
878
- )
879
- else
880
- inline_block("
881
- pframe->target_frame = (void*)-1;
882
- pframe->exception = #{literal_value LocalJumpError.exception};
883
- longjmp(pframe->jmp,1);
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
- "Qnil; pframe->target_frame = (void*)-3; pframe->return_value = #{tree[1] ? to_c(tree[1]) : "Qnil"}; longjmp(pframe->jmp,1)"
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->target_frame = (void*)-1;
896
- pframe->exception = #{literal_value LocalJumpError.exception};
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
- # this subtree is a when
992
- subtree[1][1..-1].map{|subsubtree|
993
- c_calltree = s(:call, nil, :inline_c, s(:arglist, s(:str, tmpvarname), s(:false)))
994
- calltree = s(:call, subsubtree, :===, s(:arglist, c_calltree))
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
- }.join("\n")
971
+ }.join("\n")
1002
972
 
1003
- }.join("\n")
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
- void* stack_chunk;
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 (frame.target_frame == (void*)-1) {
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.target_frame != &frame) {
1125
- VALUE ex = rb_funcall(
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 current_thread = rb_thread_current();
1403
- VALUE rb_stack_chunk = Qnil;
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 (frame.stack_chunk == 0) {
1407
- frame.stack_chunk = get_stack_chunk_from_context(&stack_chunk_reference,&rb_stack_chunk);
1363
+ if (rb_stack_chunk != Qnil) {
1364
+ Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
1408
1365
  }
1409
1366
 
1410
- if (frame.stack_chunk == 0 || (frame.stack_chunk == 0 ? 0 : stack_chunk_frozen(frame.stack_chunk)) ) {
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
- frame.stack_chunk = create_stack_chunk_from_context(&stack_chunk_reference,&rb_stack_chunk);
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(frame.stack_chunk);
1380
+ int previous_stack_position = stack_chunk_get_current_position(stack_chunk);
1419
1381
 
1420
- plocals = (typeof(plocals))stack_chunk_alloc(frame.stack_chunk ,sizeof(typeof(*plocals))/sizeof(void*));
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(frame.stack_chunk, previous_stack_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
- stack_chunk_reference_assign(stack_chunk_reference, rb_previous_stack_chunk);
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(frame.stack_chunk, previous_stack_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
- stack_chunk_reference_assign(stack_chunk_reference, rb_previous_stack_chunk);
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 current_thread = rb_thread_current();
1498
- VALUE rb_stack_chunk = Qnil;
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 (frame.stack_chunk == 0) {
1502
- frame.stack_chunk = get_stack_chunk_from_context(&stack_chunk_reference,&rb_stack_chunk);
1456
+ if (rb_stack_chunk != Qnil) {
1457
+ Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
1503
1458
  }
1504
1459
 
1505
- if (frame.stack_chunk == 0 || (frame.stack_chunk == 0 ? 0 : stack_chunk_frozen(frame.stack_chunk)) ) {
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
- frame.stack_chunk = create_stack_chunk_from_context(&stack_chunk_reference,&rb_stack_chunk);
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(frame.stack_chunk);
1476
+ int previous_stack_position = stack_chunk_get_current_position(stack_chunk);
1517
1477
 
1518
- plocals = (typeof(plocals))stack_chunk_alloc(frame.stack_chunk ,sizeof(typeof(*plocals))/sizeof(void*));
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(frame.stack_chunk, previous_stack_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
- stack_chunk_reference_assign(stack_chunk_reference, rb_previous_stack_chunk);
1497
+ frame.thread_data->rb_stack_chunk = rb_previous_stack_chunk;
1538
1498
  }
1539
1499
 
1540
- if (pframe->target_frame != pframe) {
1541
- // raise exception
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(frame.stack_chunk, previous_stack_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
- stack_chunk_reference_assign(stack_chunk_reference, rb_previous_stack_chunk);
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
- frame(to_c(tree[1])+";","
1715
- if (CLASS_OF(frame.exception) == #{to_c(resbody_tree[1][1])})
1716
- {
1717
- // trap exception
1718
- ;original_frame->target_frame = &frame;
1719
- #{to_c(resbody_tree[2])};
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->target_frame = (void*)-1;
1750
- pframe->exception = rb_funcall(#{to_c args[1]}, #{intern_num :exception},0);
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 current_thread = rb_thread_current();
1887
- VALUE rb_stack_chunk = Qnil;
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 (frame.stack_chunk == 0) {
1891
- frame.stack_chunk = get_stack_chunk_from_context(&stack_chunk_reference,&rb_stack_chunk);
1853
+ if (rb_stack_chunk != Qnil) {
1854
+ Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
1892
1855
  }
1893
1856
 
1894
- if (frame.stack_chunk == 0 || (frame.stack_chunk == 0 ? 0 : stack_chunk_frozen(frame.stack_chunk)) ) {
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
- frame.stack_chunk = create_stack_chunk_from_context(&stack_chunk_reference,&rb_stack_chunk);
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(frame.stack_chunk);
1870
+ int previous_stack_position = stack_chunk_get_current_position(stack_chunk);
1903
1871
 
1904
- plocals = (typeof(plocals))stack_chunk_alloc(frame.stack_chunk ,sizeof(typeof(*plocals))/sizeof(void*));
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(frame.stack_chunk, previous_stack_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
- stack_chunk_reference_assign(stack_chunk_reference, rb_previous_stack_chunk);
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.stack_chunk = 0;
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
- if (setjmp(frame.jmp) != 0) {
2162
- parent_frame->target_frame = frame.target_frame;
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
- return frame.return_value;
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.stack_chunk = 0;
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
- if (setjmp(frame.jmp) != 0) {
2203
- parent_frame->target_frame = frame.target_frame;
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
- return frame.return_value;
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
- rescue_code = "rb_rescue2(#{body},#{rescue_args},#{anonymous_function{|name| "
2219
- static VALUE #{name}(VALUE param, VALUE error) {
2220
- #{@frame_struct} *pframe = (void*)param;
2221
- pframe->last_error = error;
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
- ,(VALUE)pframe, rb_eException,(VALUE)0)"
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->target_frame != pframe) {
2281
- // raise exception
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->target_frame != original_frame) {
2571
- pframe->exception = original_frame->exception;
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;