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.
@@ -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;