fastruby 0.0.7 → 0.0.8

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.
@@ -53,6 +53,7 @@ module FastRuby
53
53
  VALUE exception;
54
54
  int rescue;
55
55
  VALUE last_error;
56
+ void* stack_chunk;
56
57
  }"
57
58
 
58
59
  @block_struct = "struct {
@@ -61,8 +62,14 @@ module FastRuby
61
62
  }"
62
63
 
63
64
 
64
- extra_code << '#include "node.h"
65
- '
65
+ extra_code << "
66
+ #include \"node.h\"
67
+
68
+ #ifndef __INLINE_FASTRUBY_BASE
69
+ #include \"#{FastRuby.fastruby_load_path}/../ext/fastruby_base/fastruby_base.inl\"
70
+ #define __INLINE_FASTRUBY_BASE
71
+ #endif
72
+ "
66
73
 
67
74
  ruby_code = "
68
75
  $LOAD_PATH << #{FastRuby.fastruby_load_path.inspect}
@@ -73,6 +80,8 @@ module FastRuby
73
80
  rb_eval_string(#{ruby_code.inspect});
74
81
  "
75
82
 
83
+
84
+
76
85
  @common_func = common_func
77
86
  if common_func
78
87
  extra_code << "static VALUE _rb_gvar_set(void* ge,VALUE value) {
@@ -82,7 +91,13 @@ module FastRuby
82
91
  "
83
92
 
84
93
  extra_code << "static VALUE re_yield(int argc, VALUE* argv, VALUE param, VALUE _parent_frame) {
85
- return rb_yield_splat(rb_ary_new4(argc,argv));
94
+ VALUE yield_args = rb_ary_new4(argc,argv);
95
+ VALUE* yield_args_p = &yield_args;
96
+
97
+ #{@frame_struct}* pframe;
98
+ pframe = (typeof(pframe))_parent_frame;
99
+
100
+ return #{protected_block("rb_yield_splat(*(VALUE*)yield_args_p)",true,"yield_args_p",true)};
86
101
  }"
87
102
 
88
103
  extra_code << "static VALUE _rb_ivar_set(VALUE recv,ID idvar, VALUE value) {
@@ -106,6 +121,55 @@ module FastRuby
106
121
  #{caller.join("\n")}
107
122
  */
108
123
 
124
+ "
125
+ extra_code << "static struct STACKCHUNKREFRENCE* get_stack_chunk_reference_from_context() {
126
+ struct STACKCHUNKREFERENCE* stack_chunk_reference;
127
+ VALUE current_thread = rb_thread_current();
128
+ VALUE rb_stack_chunk_reference = rb_ivar_get(current_thread,#{intern_num :_fastruby_stack_chunk_reference});
129
+ if (rb_stack_chunk_reference == Qnil) {
130
+ rb_stack_chunk_reference = rb_stack_chunk_reference_create();
131
+ rb_ivar_set(current_thread,#{intern_num :_fastruby_stack_chunk_reference},rb_stack_chunk_reference);
132
+ }
133
+
134
+ Data_Get_Struct(rb_stack_chunk_reference,struct STACKCHUNKREFERENCE,stack_chunk_reference);
135
+
136
+ return (void*)stack_chunk_reference;
137
+ }
138
+
139
+ static struct STACKCHUNK* get_stack_chunk_from_context(
140
+ struct STACKCHUNKREFERENCE** stack_chunk_reference,
141
+ VALUE* rb_stack_chunk
142
+ ) {
143
+ struct STACKCHUNK* stack_chunk = 0;
144
+ *stack_chunk_reference = (void*)get_stack_chunk_reference_from_context();
145
+ *rb_stack_chunk = stack_chunk_reference_retrieve(*stack_chunk_reference);
146
+ if (*rb_stack_chunk != Qnil) {
147
+ Data_Get_Struct(*rb_stack_chunk,void,stack_chunk);
148
+ }
149
+
150
+ return stack_chunk;
151
+ }
152
+
153
+ static struct STACKCHUNK* create_stack_chunk_from_context(
154
+ struct STACKCHUNKREFERENCE** stack_chunk_reference,
155
+ VALUE* rb_stack_chunk_p
156
+ ) {
157
+
158
+ struct STACKCHUNK* stack_chunk;
159
+ VALUE rb_stack_chunk = rb_stack_chunk_create(Qnil);
160
+
161
+ if (*stack_chunk_reference == 0) {
162
+ *stack_chunk_reference = (void*)get_stack_chunk_reference_from_context();
163
+ }
164
+
165
+ stack_chunk_reference_assign(*stack_chunk_reference, rb_stack_chunk);
166
+ Data_Get_Struct(rb_stack_chunk,void,stack_chunk);
167
+
168
+ *rb_stack_chunk_p = rb_stack_chunk;
169
+
170
+ return stack_chunk;
171
+ }
172
+
109
173
  "
110
174
  end
111
175
  end
@@ -225,13 +289,13 @@ module FastRuby
225
289
  to_c(subtree)
226
290
  }.join(";")
227
291
 
228
- if anonymous_impl[-1][0] != :return
292
+ if anonymous_impl[-1][0] != :return and anonymous_impl[-1][0] != :break and anonymous_impl[-1][0] != :next
229
293
  str_impl = str_impl + ";last_expression = (#{to_c(anonymous_impl[-1])});"
230
294
  else
231
295
  str_impl = str_impl + ";#{to_c(anonymous_impl[-1])};"
232
296
  end
233
297
  else
234
- if anonymous_impl[0] != :return
298
+ if anonymous_impl[0] != :return and anonymous_impl[0] != :break and anonymous_impl[0] != :next
235
299
  str_impl = str_impl + ";last_expression = (#{to_c(anonymous_impl)});"
236
300
  else
237
301
  str_impl = str_impl + ";#{to_c(anonymous_impl)};"
@@ -278,33 +342,92 @@ module FastRuby
278
342
  str_recv = to_c recv_tree
279
343
  str_recv = "plocals->self" unless recv_tree
280
344
 
345
+ execute_code = if mname == :lambda or mname == :proc
346
+ "VALUE ret = rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, 0);
347
+
348
+ // freeze all stacks
349
+ VALUE current_thread = rb_thread_current();
350
+ VALUE rb_stack_chunk_reference = rb_ivar_get(current_thread,#{intern_num :_fastruby_stack_chunk_reference});
351
+
352
+ if (rb_stack_chunk_reference != Qnil) {
353
+ struct STACKCHUNKREFERENCE* stack_chunk_reference;
354
+ Data_Get_Struct(rb_stack_chunk_reference, struct STACKCHUNKREFERENCE, stack_chunk_reference);
355
+
356
+ VALUE rb_stack_chunk = stack_chunk_reference_retrieve(stack_chunk_reference);
357
+
358
+ // add reference to stack chunk to lambda object
359
+ rb_ivar_set(ret,#{intern_num :_fastruby_stack_chunk},rb_stack_chunk);
360
+
361
+ // freeze the complete chain of stack chunks
362
+ while (rb_stack_chunk != Qnil) {
363
+ struct STACKCHUNK* stack_chunk;
364
+ Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
365
+
366
+ stack_chunk_freeze(stack_chunk);
367
+
368
+ rb_stack_chunk = rb_ivar_get(rb_stack_chunk,#{intern_num :_parent_stack_chunk});
369
+ }
370
+ }
371
+
372
+ return ret;
373
+ "
374
+ else
375
+ "return rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, 0);"
376
+ end
377
+
281
378
  rb_funcall_caller_code = proc { |name| "
282
379
  static VALUE #{name}(VALUE param) {
283
380
  // call to #{call_tree[2]}
284
381
  #{str_lvar_initialization}
285
- return rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, 0);
382
+ #{execute_code}
286
383
  }
287
384
  "
288
385
  }
289
386
  end
290
387
 
388
+ target_escape_code = if mname == :lambda or mname == :proc
389
+ "
390
+ // create a fake parent frame representing the lambda method frame and a fake locals scope
391
+ #{@locals_struct} fake_locals;
392
+ #{@frame_struct} fake_frame;
291
393
 
292
- rb_funcall_block_code = proc { |name| "
293
- static VALUE #{name}(VALUE arg, VALUE _plocals) {
294
- // block for call to #{call_tree[2]}
295
- VALUE last_expression = Qnil;
394
+ fake_frame.plocals = (void*)&fake_locals;
395
+ fake_frame.parent_frame = 0;
296
396
 
297
- #{@frame_struct} frame;
298
- #{@frame_struct} *pframe = (void*)&frame;
299
- #{@locals_struct} *plocals = (void*)_plocals;
397
+ fake_locals.pframe = LONG2FIX(&fake_frame);
300
398
 
301
- frame.plocals = plocals;
302
- frame.parent_frame = 0;
303
- frame.return_value = Qnil;
304
- frame.target_frame = &frame;
305
- frame.exception = Qnil;
306
- frame.rescue = 0;
399
+ VALUE old_call_frame = ((typeof(fake_locals)*)(pframe->plocals))->call_frame;
400
+ ((typeof(fake_locals)*)(pframe->plocals))->call_frame = LONG2FIX(pframe);
401
+
402
+ frame.parent_frame = (void*)&fake_frame;
403
+
404
+ if (setjmp(frame.jmp) != 0) {
405
+
406
+ if (pframe->target_frame != pframe) {
407
+ if (pframe->target_frame == (void*)-3) {
408
+ return pframe->return_value;
409
+ } else if (pframe->target_frame == (void*)-1) {
410
+ rb_funcall(((typeof(fake_locals)*)(pframe->plocals))->self, #{intern_num :raise}, 1, frame.exception);
411
+ return Qnil;
412
+ } else {
413
+ if (pframe->target_frame == (void*)FIX2LONG(plocals->pframe)) {
414
+ ((typeof(fake_locals)*)(pframe->plocals))->call_frame = old_call_frame;
415
+ return pframe->return_value;
416
+ } else if (pframe->target_frame == (void*)&fake_frame) {
417
+ ((typeof(fake_locals)*)(pframe->plocals))->call_frame = old_call_frame;
418
+ return fake_locals.return_value;
419
+ } else {
420
+ rb_raise(rb_eLocalJumpError, \"unexpected return\");
421
+ }
422
+ }
423
+ }
424
+ ((typeof(fake_locals)*)(pframe->plocals))->call_frame = old_call_frame;
425
+ return frame.return_value;
426
+ }
307
427
 
428
+ "
429
+ else
430
+ "
308
431
  if (setjmp(frame.jmp) != 0) {
309
432
  if (pframe->target_frame != pframe) {
310
433
  if (pframe->target_frame == (void*)-3) {
@@ -321,14 +444,38 @@ module FastRuby
321
444
  );
322
445
 
323
446
  rb_funcall(plocals->self, #{intern_num :raise}, 1, ex);
447
+ }
448
+ return frame.return_value;
324
449
  }
325
- return frame.return_value;
326
- }
450
+
451
+ "
452
+ end
453
+
454
+ rb_funcall_block_code = proc { |name| "
455
+ static VALUE #{name}(VALUE arg, VALUE _plocals) {
456
+ // block for call to #{call_tree[2]}
457
+ VALUE last_expression = Qnil;
458
+
459
+ #{@frame_struct} frame;
460
+ #{@frame_struct} *pframe = (void*)&frame;
461
+ #{@locals_struct} *plocals = (void*)_plocals;
462
+
463
+ frame.plocals = plocals;
464
+ frame.stack_chunk = 0;
465
+ frame.parent_frame = 0;
466
+ frame.return_value = Qnil;
467
+ frame.target_frame = &frame;
468
+ frame.exception = Qnil;
469
+ frame.rescue = 0;
470
+
471
+ #{target_escape_code}
327
472
 
328
473
 
329
474
  #{str_arg_initialization}
330
475
  #{str_impl}
331
476
 
477
+ #{"((typeof(fake_locals)*)(pframe->plocals))->call_frame = old_call_frame;" if mname == :lambda or mname == :proc}
478
+
332
479
  return last_expression;
333
480
  }
334
481
  "
@@ -360,6 +507,7 @@ module FastRuby
360
507
 
361
508
  frame.plocals = (void*)_locals;
362
509
  frame.parent_frame = parent_frame;
510
+ frame.stack_chunk = parent_frame->stack_chunk;
363
511
  frame.return_value = Qnil;
364
512
  frame.target_frame = &frame;
365
513
  frame.exception = Qnil;
@@ -376,6 +524,7 @@ module FastRuby
376
524
  ((typeof(pframe))_parent_frame)->exception = pframe->exception;
377
525
  ((typeof(pframe))_parent_frame)->target_frame = pframe->target_frame;
378
526
  ((typeof(pframe))_parent_frame)->return_value = pframe->return_value;
527
+
379
528
  longjmp(((typeof(pframe))_parent_frame)->jmp,1);
380
529
  }
381
530
 
@@ -427,9 +576,36 @@ module FastRuby
427
576
  block.block_function_address = (void*)#{anonymous_function(&block_code)};
428
577
  block.block_function_param = (void*)param;
429
578
 
430
- // call to #{call_tree[2]}
579
+ // create a call_frame
580
+ #{@frame_struct} call_frame;
581
+
582
+ call_frame.parent_frame = (void*)pframe;
583
+ call_frame.target_frame = 0;
584
+ call_frame.plocals = plocals;
585
+ call_frame.return_value = Qnil;
586
+ call_frame.exception = Qnil;
587
+ call_frame.stack_chunk = ((typeof(&call_frame))pframe)->stack_chunk;
431
588
 
432
- return ((VALUE(*)(VALUE,VALUE,VALUE))#{encode_address(recvtype,signature,mname,call_tree,inference_complete,convention_global_name)})(#{str_recv}, (VALUE)&block, (VALUE)pframe);
589
+ VALUE old_call_frame = plocals->call_frame;
590
+ plocals->call_frame = LONG2FIX(&call_frame);
591
+
592
+ if (setjmp(call_frame.jmp) != 0) {
593
+ #{@frame_struct}* pframe_ = (void*)pframe;
594
+
595
+ if (call_frame.target_frame != &call_frame) {
596
+ pframe_->target_frame = call_frame.target_frame;
597
+ pframe_->exception = call_frame.exception;
598
+ longjmp(pframe_->jmp,1);
599
+ }
600
+
601
+ plocals->call_frame = old_call_frame;
602
+ return call_frame.return_value;
603
+ }
604
+
605
+ // call to #{call_tree[2]}
606
+ 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);
607
+ plocals->call_frame = old_call_frame;
608
+ return ret;
433
609
  }
434
610
  "
435
611
  }
@@ -440,12 +616,51 @@ module FastRuby
440
616
  return #{anonymous_function(&caller_code)}((VALUE)plocals, (VALUE)pframe);
441
617
  } else {
442
618
  return #{
443
- protected_block("rb_iterate(#{anonymous_function(&rb_funcall_caller_code)}, (VALUE)pframe, #{anonymous_function(&rb_funcall_block_code)}, (VALUE)plocals)", true)
619
+ frame_call(
620
+ protected_block("rb_iterate(#{anonymous_function(&rb_funcall_caller_code)}, (VALUE)pframe, #{anonymous_function(&rb_funcall_block_code)}, (VALUE)plocals)", true)
621
+ )
444
622
  };
445
623
  }
446
624
  "
447
625
  end
448
626
 
627
+ def frame_call(inner_code)
628
+ inline_block "
629
+
630
+
631
+ // create a call_frame
632
+ #{@frame_struct} call_frame;
633
+ typeof(call_frame)* old_pframe = (void*)pframe;
634
+
635
+ pframe = (typeof(pframe))&call_frame;
636
+
637
+ call_frame.parent_frame = (void*)pframe;
638
+ call_frame.target_frame = 0;
639
+ call_frame.plocals = plocals;
640
+ call_frame.return_value = Qnil;
641
+ call_frame.exception = Qnil;
642
+ call_frame.stack_chunk = ((typeof(&call_frame))pframe)->stack_chunk;
643
+
644
+ VALUE old_call_frame = plocals->call_frame;
645
+ plocals->call_frame = LONG2FIX(&call_frame);
646
+
647
+ if (setjmp(call_frame.jmp) != 0) {
648
+ if (call_frame.target_frame != &call_frame) {
649
+ old_pframe->target_frame = call_frame.target_frame;
650
+ old_pframe->exception = call_frame.exception;
651
+ longjmp(old_pframe->jmp,1);
652
+ }
653
+
654
+ plocals->call_frame = old_call_frame;
655
+ return call_frame.return_value;
656
+ }
657
+
658
+ VALUE ret = #{inner_code};
659
+ plocals->call_frame = old_call_frame;
660
+ return ret;
661
+ "
662
+ end
663
+
449
664
  def to_c_yield(tree)
450
665
 
451
666
  block_code = proc { |name| "
@@ -456,10 +671,10 @@ module FastRuby
456
671
  pframe = (void*)frame_param;
457
672
  plocals = (void*)pframe->plocals;
458
673
 
459
- if (plocals->block_function_address == 0) {
674
+ if (FIX2LONG(plocals->block_function_address) == 0) {
460
675
  rb_raise(rb_eLocalJumpError, \"no block given\");
461
676
  } else {
462
- return ((VALUE(*)(int,VALUE*,VALUE,VALUE))plocals->block_function_address)(#{tree.size-1}, block_args, plocals->block_function_param, (VALUE)pframe);
677
+ return ((VALUE(*)(int,VALUE*,VALUE,VALUE))FIX2LONG(plocals->block_function_address))(#{tree.size-1}, block_args, FIX2LONG(plocals->block_function_param), (VALUE)pframe);
463
678
  }
464
679
  }
465
680
  "
@@ -520,15 +735,27 @@ module FastRuby
520
735
  end
521
736
 
522
737
  def to_c_return(tree)
523
- "pframe->target_frame = ((typeof(pframe))plocals->pframe); plocals->return_value = #{to_c(tree[1])}; longjmp(pframe->jmp, 1); return Qnil;\n"
738
+ "pframe->target_frame = ((typeof(pframe))FIX2LONG(plocals->pframe)); plocals->return_value = #{to_c(tree[1])}; pframe->return_value = plocals->return_value; longjmp(pframe->jmp, 1); return Qnil;\n"
524
739
  end
525
740
 
526
741
  def to_c_break(tree)
527
742
  if @on_block
528
743
  inline_block(
529
744
  "
530
- pframe->target_frame = (void*)-2;
531
- pframe->return_value = #{tree[1] ? to_c(tree[1]) : "Qnil"};
745
+
746
+ VALUE value = #{tree[1] ? to_c(tree[1]) : "Qnil"};
747
+
748
+ typeof(pframe) target_frame_;
749
+ target_frame_ = (void*)FIX2LONG(plocals->call_frame);
750
+
751
+ if (target_frame_ == 0) {
752
+ rb_raise(rb_eLocalJumpError, \"illegal break\");
753
+ }
754
+
755
+ plocals->call_frame = LONG2FIX(0);
756
+
757
+ pframe->target_frame = target_frame_;
758
+ pframe->return_value = value;
532
759
  pframe->exception = Qnil;
533
760
  longjmp(pframe->jmp,1);"
534
761
  )
@@ -744,8 +971,11 @@ module FastRuby
744
971
  VALUE return_value;
745
972
  VALUE exception;
746
973
  int rescue;
974
+ VALUE last_error;
975
+ void* stack_chunk;
747
976
  } frame;
748
977
 
978
+ frame.stack_chunk = 0;
749
979
  frame.target_frame = 0;
750
980
  frame.parent_frame = 0;
751
981
  frame.rescue = 0;
@@ -890,35 +1120,15 @@ module FastRuby
890
1120
 
891
1121
  def initialize_method_structs(args_tree)
892
1122
  @locals_struct = "struct {
893
- void* block_function_address;
894
- VALUE block_function_param;
895
- jmp_buf jmp;
896
1123
  VALUE return_value;
897
- void* pframe;
1124
+ VALUE pframe;
1125
+ VALUE block_function_address;
1126
+ VALUE block_function_param;
1127
+ VALUE call_frame;
898
1128
  #{@locals.map{|l| "VALUE #{l};\n"}.join}
899
1129
  #{args_tree[1..-1].map{|arg| "VALUE #{arg};\n"}.join};
900
1130
  }"
901
1131
 
902
- if @common_func
903
- init_extra << "
904
- #{@frame_struct} frame;
905
- #{@locals_struct} locals;
906
-
907
- locals.return_value = Qnil;
908
- locals.pframe = &frame;
909
- locals.self = rb_cObject;
910
-
911
- frame.target_frame = 0;
912
- frame.plocals = (void*)&locals;
913
- frame.return_value = Qnil;
914
- frame.exception = Qnil;
915
- frame.rescue = 0;
916
- frame.last_error = Qnil;
917
-
918
- typeof(&frame) pframe = &frame;
919
- "
920
- end
921
-
922
1132
  end
923
1133
 
924
1134
  def to_c_method_defs(tree)
@@ -940,11 +1150,11 @@ module FastRuby
940
1150
  #{func_frame}
941
1151
 
942
1152
  #{args_tree[1..-1].map { |arg|
943
- "locals.#{arg} = #{arg};\n"
1153
+ "plocals->#{arg} = #{arg};\n"
944
1154
  }.join("") }
945
1155
 
946
- locals.block_function_address = block_address;
947
- locals.block_function_param = block_param;
1156
+ plocals->block_function_address = LONG2FIX(block_address);
1157
+ plocals->block_function_param = LONG2FIX(block_param);
948
1158
 
949
1159
  return #{to_c impl_tree};
950
1160
  }"
@@ -971,7 +1181,7 @@ module FastRuby
971
1181
  void* block_address = 0;
972
1182
  VALUE block_param = Qnil;
973
1183
 
974
-
1184
+ frame.stack_chunk = 0;
975
1185
  frame.plocals = 0;
976
1186
  frame.parent_frame = 0;
977
1187
  frame.return_value = Qnil;
@@ -1057,19 +1267,41 @@ module FastRuby
1057
1267
 
1058
1268
  ret = "VALUE #{@alt_method_name || method_name}() {
1059
1269
 
1060
- #{@locals_struct} locals;
1061
- #{@locals_struct} *plocals = (void*)&locals;
1270
+ #{@locals_struct} *plocals;
1062
1271
  #{@frame_struct} frame;
1063
1272
  #{@frame_struct} *pframe;
1064
1273
 
1065
- frame.plocals = plocals;
1274
+ frame.stack_chunk = 0;
1066
1275
  frame.parent_frame = 0;
1067
1276
  frame.return_value = Qnil;
1068
1277
  frame.target_frame = &frame;
1069
1278
  frame.exception = Qnil;
1070
1279
  frame.rescue = 0;
1071
1280
 
1072
- locals.pframe = &frame;
1281
+
1282
+ int stack_chunk_instantiated = 0;
1283
+ VALUE rb_previous_stack_chunk = Qnil;
1284
+ VALUE current_thread = rb_thread_current();
1285
+ VALUE rb_stack_chunk = Qnil;
1286
+ struct STACKCHUNKREFERENCE* stack_chunk_reference = 0;
1287
+
1288
+ if (frame.stack_chunk == 0) {
1289
+ frame.stack_chunk = get_stack_chunk_from_context(&stack_chunk_reference,&rb_stack_chunk);
1290
+ }
1291
+
1292
+ if (frame.stack_chunk == 0 || (frame.stack_chunk == 0 ? 0 : stack_chunk_frozen(frame.stack_chunk)) ) {
1293
+ rb_previous_stack_chunk = rb_stack_chunk;
1294
+ rb_gc_register_address(&rb_stack_chunk);
1295
+ stack_chunk_instantiated = 1;
1296
+
1297
+ frame.stack_chunk = create_stack_chunk_from_context(&stack_chunk_reference,&rb_stack_chunk);
1298
+ }
1299
+
1300
+ int previous_stack_position = stack_chunk_get_current_position(frame.stack_chunk);
1301
+
1302
+ plocals = (typeof(plocals))stack_chunk_alloc(frame.stack_chunk ,sizeof(typeof(*plocals))/sizeof(void*));
1303
+ plocals->pframe = LONG2FIX(&frame);
1304
+ frame.plocals = plocals;
1073
1305
 
1074
1306
  pframe = (void*)&frame;
1075
1307
 
@@ -1077,9 +1309,11 @@ module FastRuby
1077
1309
 
1078
1310
  int aux = setjmp(pframe->jmp);
1079
1311
  if (aux != 0) {
1312
+ stack_chunk_set_current_position(frame.stack_chunk, previous_stack_position);
1080
1313
 
1081
- if (pframe->target_frame == (void*)-2) {
1082
- return pframe->return_value;
1314
+ if (stack_chunk_instantiated) {
1315
+ rb_gc_unregister_address(&rb_stack_chunk);
1316
+ stack_chunk_reference_assign(stack_chunk_reference, rb_previous_stack_chunk);
1083
1317
  }
1084
1318
 
1085
1319
  if (pframe->target_frame != pframe) {
@@ -1090,16 +1324,26 @@ module FastRuby
1090
1324
  return plocals->return_value;
1091
1325
  }
1092
1326
 
1093
- locals.self = self;
1327
+ plocals->self = self;
1094
1328
 
1095
1329
  #{args_tree[1..-1].map { |arg|
1096
- "locals.#{arg} = #{arg};\n"
1330
+ "plocals->#{arg} = #{arg};\n"
1097
1331
  }.join("") }
1098
1332
 
1099
- locals.block_function_address = 0;
1100
- locals.block_function_param = Qnil;
1333
+ plocals->block_function_address = LONG2FIX(0);
1334
+ plocals->block_function_param = LONG2FIX(Qnil);
1335
+ plocals->call_frame = LONG2FIX(0);
1336
+
1337
+ VALUE ret = #{to_c impl_tree};
1338
+ stack_chunk_set_current_position(frame.stack_chunk, previous_stack_position);
1339
+
1340
+ if (stack_chunk_instantiated) {
1341
+ rb_gc_unregister_address(&rb_stack_chunk);
1342
+ stack_chunk_reference_assign(stack_chunk_reference, rb_previous_stack_chunk);
1343
+ }
1344
+
1345
+ return ret;
1101
1346
 
1102
- return #{to_c impl_tree};
1103
1347
  }"
1104
1348
 
1105
1349
  add_main
@@ -1116,22 +1360,94 @@ module FastRuby
1116
1360
 
1117
1361
  ret = "VALUE #{@alt_method_name || method_name}(#{strargs}) {
1118
1362
 
1119
- #{func_frame}
1363
+ #{@frame_struct} frame;
1364
+ #{@frame_struct} *pframe;
1365
+
1366
+ frame.parent_frame = (void*)_parent_frame;
1367
+ frame.stack_chunk = ((typeof(pframe))_parent_frame)->stack_chunk;
1368
+ frame.return_value = Qnil;
1369
+ frame.target_frame = &frame;
1370
+ frame.exception = Qnil;
1371
+ frame.rescue = 0;
1372
+
1373
+ int stack_chunk_instantiated = 0;
1374
+ VALUE rb_previous_stack_chunk = Qnil;
1375
+ VALUE current_thread = rb_thread_current();
1376
+ VALUE rb_stack_chunk = Qnil;
1377
+ struct STACKCHUNKREFERENCE* stack_chunk_reference = 0;
1378
+
1379
+ if (frame.stack_chunk == 0) {
1380
+ frame.stack_chunk = get_stack_chunk_from_context(&stack_chunk_reference,&rb_stack_chunk);
1381
+ }
1382
+
1383
+ if (frame.stack_chunk == 0 || (frame.stack_chunk == 0 ? 0 : stack_chunk_frozen(frame.stack_chunk)) ) {
1384
+ rb_previous_stack_chunk = rb_stack_chunk;
1385
+ rb_gc_register_address(&rb_stack_chunk);
1386
+ stack_chunk_instantiated = 1;
1387
+
1388
+ frame.stack_chunk = create_stack_chunk_from_context(&stack_chunk_reference,&rb_stack_chunk);
1389
+ }
1390
+
1391
+
1392
+ #{@locals_struct} *plocals;
1393
+
1394
+ int previous_stack_position = stack_chunk_get_current_position(frame.stack_chunk);
1395
+
1396
+ plocals = (typeof(plocals))stack_chunk_alloc(frame.stack_chunk ,sizeof(typeof(*plocals))/sizeof(void*));
1397
+ frame.plocals = plocals;
1398
+ plocals->pframe = LONG2FIX(&frame);
1399
+ plocals->call_frame = LONG2FIX(0);
1400
+
1401
+ pframe = (void*)&frame;
1402
+
1403
+ #{@block_struct} *pblock;
1404
+ VALUE last_expression = Qnil;
1405
+
1406
+ int aux = setjmp(pframe->jmp);
1407
+ if (aux != 0) {
1408
+ stack_chunk_set_current_position(frame.stack_chunk, previous_stack_position);
1409
+
1410
+ if (stack_chunk_instantiated) {
1411
+ rb_gc_unregister_address(&rb_stack_chunk);
1412
+ stack_chunk_reference_assign(stack_chunk_reference, rb_previous_stack_chunk);
1413
+ }
1414
+
1415
+ if (pframe->target_frame != pframe) {
1416
+ // raise exception
1417
+ ((typeof(pframe))_parent_frame)->exception = pframe->exception;
1418
+ ((typeof(pframe))_parent_frame)->target_frame = pframe->target_frame;
1419
+ ((typeof(pframe))_parent_frame)->return_value = pframe->return_value;
1420
+
1421
+ longjmp(((typeof(pframe))_parent_frame)->jmp,1);
1422
+ }
1423
+
1424
+ return plocals->return_value;
1425
+ }
1426
+
1427
+ plocals->self = self;
1120
1428
 
1121
1429
  #{args_tree[1..-1].map { |arg|
1122
- "locals.#{arg} = #{arg};\n"
1430
+ "plocals->#{arg} = #{arg};\n"
1123
1431
  }.join("") }
1124
1432
 
1125
1433
  pblock = (void*)block;
1126
1434
  if (pblock) {
1127
- locals.block_function_address = pblock->block_function_address;
1128
- locals.block_function_param = (VALUE)pblock->block_function_param;
1435
+ plocals->block_function_address = LONG2FIX(pblock->block_function_address);
1436
+ plocals->block_function_param = LONG2FIX(pblock->block_function_param);
1129
1437
  } else {
1130
- locals.block_function_address = 0;
1131
- locals.block_function_param = Qnil;
1438
+ plocals->block_function_address = LONG2FIX(0);
1439
+ plocals->block_function_param = LONG2FIX(Qnil);
1440
+ }
1441
+
1442
+ VALUE __ret = #{to_c impl_tree};
1443
+ stack_chunk_set_current_position(frame.stack_chunk, previous_stack_position);
1444
+
1445
+ if (stack_chunk_instantiated) {
1446
+ rb_gc_unregister_address(&rb_stack_chunk);
1447
+ stack_chunk_reference_assign(stack_chunk_reference, rb_previous_stack_chunk);
1132
1448
  }
1133
1449
 
1134
- return #{to_c impl_tree};
1450
+ return __ret;
1135
1451
  }"
1136
1452
 
1137
1453
  add_main
@@ -1396,12 +1712,12 @@ module FastRuby
1396
1712
  old_locals_struct = @locals_struct
1397
1713
 
1398
1714
  @locals = locals
1399
- @locals_struct = "struct {
1400
- void* block_function_address;
1401
- VALUE block_function_param;
1402
- jmp_buf jmp;
1715
+ @locals_struct = "struct {
1403
1716
  VALUE return_value;
1404
- void* pframe;
1717
+ VALUE pframe;
1718
+ VALUE block_function_address;
1719
+ VALUE block_function_param;
1720
+ VALUE call_frame;
1405
1721
  #{@locals.map{|l| "VALUE #{l};\n"}.join}
1406
1722
  }"
1407
1723
 
@@ -1428,20 +1744,51 @@ module FastRuby
1428
1744
  fun = anonymous_function { |method_name| "static VALUE #{method_name}(VALUE self) {
1429
1745
 
1430
1746
  #{@frame_struct} frame;
1431
- #{@locals_struct} locals;
1432
1747
  typeof(&frame) pframe = &frame;
1433
- typeof(&locals) plocals = &locals;
1748
+ #{@locals_struct} *plocals;
1434
1749
 
1435
- frame.plocals = plocals;
1750
+ frame.stack_chunk = 0;
1436
1751
  frame.parent_frame = 0;
1437
1752
  frame.return_value = Qnil;
1438
1753
  frame.target_frame = &frame;
1439
1754
  frame.exception = Qnil;
1440
1755
  frame.rescue = 0;
1441
1756
 
1442
- locals.self = self;
1757
+ int stack_chunk_instantiated = 0;
1758
+ VALUE rb_previous_stack_chunk = Qnil;
1759
+ VALUE current_thread = rb_thread_current();
1760
+ VALUE rb_stack_chunk = Qnil;
1761
+ struct STACKCHUNKREFERENCE* stack_chunk_reference = 0;
1762
+
1763
+ if (frame.stack_chunk == 0) {
1764
+ frame.stack_chunk = get_stack_chunk_from_context(&stack_chunk_reference,&rb_stack_chunk);
1765
+ }
1766
+
1767
+ if (frame.stack_chunk == 0 || (frame.stack_chunk == 0 ? 0 : stack_chunk_frozen(frame.stack_chunk)) ) {
1768
+ rb_previous_stack_chunk = rb_stack_chunk;
1769
+ rb_gc_register_address(&rb_stack_chunk);
1770
+ stack_chunk_instantiated = 1;
1771
+
1772
+ frame.stack_chunk = create_stack_chunk_from_context(&stack_chunk_reference,&rb_stack_chunk);
1773
+ }
1774
+
1775
+ int previous_stack_position = stack_chunk_get_current_position(frame.stack_chunk);
1776
+
1777
+ plocals = (typeof(plocals))stack_chunk_alloc(frame.stack_chunk ,sizeof(typeof(*plocals))/sizeof(void*));
1778
+
1779
+ frame.plocals = plocals;
1780
+ plocals->self = self;
1781
+ plocals->call_frame = LONG2FIX(0);
1443
1782
 
1444
1783
  #{to_c tree};
1784
+
1785
+ stack_chunk_set_current_position(frame.stack_chunk, previous_stack_position);
1786
+
1787
+ if (stack_chunk_instantiated) {
1788
+ rb_gc_unregister_address(&rb_stack_chunk);
1789
+ stack_chunk_reference_assign(stack_chunk_reference, rb_previous_stack_chunk);
1790
+ }
1791
+
1445
1792
  return Qnil;
1446
1793
  }
1447
1794
  "
@@ -1559,7 +1906,7 @@ module FastRuby
1559
1906
  @infer_lvar_map[lvar_name] = lvar_type
1560
1907
  return ""
1561
1908
  elsif mname == :block_given?
1562
- return "#{locals_accessor}block_function_address == 0 ? Qfalse : Qtrue"
1909
+ return "FIX2LONG(plocals->block_function_address) == 0 ? Qfalse : Qtrue"
1563
1910
  elsif mname == :inline_c
1564
1911
 
1565
1912
  code = args[1][1]
@@ -1583,7 +1930,7 @@ module FastRuby
1583
1930
  end
1584
1931
  end
1585
1932
 
1586
- def inline_block_reference(arg)
1933
+ def inline_block_reference(arg, nolocals = false)
1587
1934
  code = nil
1588
1935
 
1589
1936
  if arg.instance_of? FastRuby::FastRubySexp
@@ -1595,7 +1942,8 @@ module FastRuby
1595
1942
  anonymous_function{ |name| "
1596
1943
  static VALUE #{name}(VALUE param) {
1597
1944
  #{@frame_struct} *pframe = (void*)param;
1598
- #{@locals_struct} *plocals = (void*)pframe->plocals;
1945
+
1946
+ #{nolocals ? "" : "#{@locals_struct} *plocals = (void*)pframe->plocals;"}
1599
1947
  VALUE last_expression = Qnil;
1600
1948
 
1601
1949
  #{code};
@@ -1605,11 +1953,12 @@ module FastRuby
1605
1953
  }
1606
1954
  end
1607
1955
 
1608
- def inline_block(code, repass_var = nil)
1956
+ def inline_block(code, repass_var = nil, nolocals = false)
1609
1957
  anonymous_function{ |name| "
1610
1958
  static VALUE #{name}(VALUE param#{repass_var ? ",void* " + repass_var : "" }) {
1611
1959
  #{@frame_struct} *pframe = (void*)param;
1612
- #{@locals_struct} *plocals = (void*)pframe->plocals;
1960
+
1961
+ #{nolocals ? "" : "#{@locals_struct} *plocals = (void*)pframe->plocals;"}
1613
1962
  VALUE last_expression = Qnil;
1614
1963
 
1615
1964
  #{code}
@@ -1622,28 +1971,16 @@ module FastRuby
1622
1971
  "rb_funcall(#{proced.__id__}, #{intern_num :call}, 1, #{parameter})"
1623
1972
  end
1624
1973
 
1625
- def wrapped_break_block(inner_code)
1626
- frame("return " + inner_code, "
1627
- if (original_frame->target_frame == (void*)-2) {
1628
- return pframe->return_value;
1629
- }
1630
- ")
1631
- end
1632
-
1633
- def protected_block(inner_code, always_rescue = false,repass_var = nil)
1974
+ def protected_block(inner_code, always_rescue = false,repass_var = nil, nolocals = false)
1634
1975
  wrapper_code = "
1635
1976
  if (pframe->last_error != Qnil) {
1636
1977
  if (CLASS_OF(pframe->last_error)==#{literal_value FastRuby::Context::UnwindFastrubyFrame}) {
1637
- #{@frame_struct} *pframe = (void*)param;
1978
+ #{@frame_struct} *pframe = (void*)param;
1638
1979
 
1639
1980
  pframe->target_frame = (void*)FIX2LONG(rb_ivar_get(pframe->last_error, #{intern_num :@target_frame}));
1640
1981
  pframe->exception = rb_ivar_get(pframe->last_error, #{intern_num :@ex});
1641
1982
  pframe->return_value = rb_ivar_get(pframe->last_error, #{intern_num :@return_value});
1642
1983
 
1643
- if (pframe->target_frame == (void*)-2) {
1644
- return pframe->return_value;
1645
- }
1646
-
1647
1984
  longjmp(pframe->jmp, 1);
1648
1985
  return Qnil;
1649
1986
 
@@ -1657,6 +1994,10 @@ module FastRuby
1657
1994
  return Qnil;
1658
1995
  }
1659
1996
 
1997
+ } else {
1998
+ if (pframe->target_frame != pframe) {
1999
+ longjmp(pframe->jmp, 1);
2000
+ }
1660
2001
  }
1661
2002
  "
1662
2003
 
@@ -1666,8 +2007,36 @@ module FastRuby
1666
2007
  if repass_var
1667
2008
  body = anonymous_function{ |name| "
1668
2009
  static VALUE #{name}(VALUE param) {
1669
- #{@frame_struct} *pframe = ((void**)param)[0];
1670
- #{@locals_struct} *plocals = pframe->plocals;
2010
+
2011
+ #{@frame_struct} frame;
2012
+
2013
+ typeof(frame)* pframe;
2014
+ typeof(frame)* parent_frame = ((typeof(pframe))((void**)param)[0]);
2015
+
2016
+ frame.parent_frame = 0;
2017
+ frame.target_frame = 0;
2018
+ frame.return_value = Qnil;
2019
+ frame.exception = Qnil;
2020
+ frame.rescue = 0;
2021
+ frame.last_error = Qnil;
2022
+ frame.stack_chunk = 0;
2023
+
2024
+ pframe = &frame;
2025
+
2026
+ #{
2027
+ nolocals ? "frame.plocals = 0;" : "#{@locals_struct}* plocals = parent_frame->plocals;
2028
+ frame.plocals = plocals;
2029
+ "
2030
+ }
2031
+
2032
+ if (setjmp(frame.jmp) != 0) {
2033
+ parent_frame->target_frame = frame.target_frame;
2034
+ parent_frame->exception = frame.exception;
2035
+ parent_frame->return_value = frame.return_value;
2036
+
2037
+ return frame.return_value;
2038
+ }
2039
+
1671
2040
  VALUE #{repass_var} = (VALUE)((void**)param)[1];
1672
2041
  return #{inner_code};
1673
2042
  }
@@ -1677,7 +2046,43 @@ module FastRuby
1677
2046
  rescue_args = ""
1678
2047
  rescue_args = "(VALUE)(VALUE[]){(VALUE)pframe,(VALUE)#{repass_var}}"
1679
2048
  else
1680
- body = inline_block_reference("return #{inner_code}")
2049
+
2050
+ body = anonymous_function{ |name| "
2051
+ static VALUE #{name}(VALUE param) {
2052
+ #{@frame_struct} frame;
2053
+
2054
+ typeof(frame)* pframe;
2055
+ typeof(frame)* parent_frame = (typeof(pframe))param;
2056
+
2057
+ frame.parent_frame = 0;
2058
+ frame.target_frame = 0;
2059
+ frame.return_value = Qnil;
2060
+ frame.exception = Qnil;
2061
+ frame.rescue = 0;
2062
+ frame.last_error = Qnil;
2063
+ frame.stack_chunk = 0;
2064
+
2065
+ pframe = &frame;
2066
+
2067
+ #{
2068
+ nolocals ? "frame.plocals = 0;" : "#{@locals_struct}* plocals = parent_frame->plocals;
2069
+ frame.plocals = plocals;
2070
+ "
2071
+ }
2072
+
2073
+ if (setjmp(frame.jmp) != 0) {
2074
+ parent_frame->target_frame = frame.target_frame;
2075
+ parent_frame->exception = frame.exception;
2076
+ parent_frame->return_value = frame.return_value;
2077
+
2078
+ return frame.return_value;
2079
+ }
2080
+
2081
+ return #{inner_code};
2082
+ }
2083
+ "
2084
+ }
2085
+
1681
2086
  rescue_args = "(VALUE)pframe"
1682
2087
  end
1683
2088
 
@@ -1692,12 +2097,13 @@ module FastRuby
1692
2097
  if always_rescue
1693
2098
  inline_block "
1694
2099
  pframe->last_error = Qnil;
2100
+ pframe->target_frame = pframe;
1695
2101
  VALUE result = #{rescue_code};
1696
2102
 
1697
2103
  #{wrapper_code}
1698
2104
 
1699
2105
  return result;
1700
- ", repass_var
2106
+ ", repass_var, nolocals
1701
2107
  else
1702
2108
  inline_block "
1703
2109
  VALUE result;
@@ -1712,7 +2118,7 @@ module FastRuby
1712
2118
  #{wrapper_code}
1713
2119
 
1714
2120
  return result;
1715
- ", repass_var
2121
+ ", repass_var, nolocals
1716
2122
  end
1717
2123
 
1718
2124
  end
@@ -1720,19 +2126,19 @@ module FastRuby
1720
2126
 
1721
2127
  def func_frame
1722
2128
  "
1723
- #{@locals_struct} locals;
1724
- #{@locals_struct} *plocals = (void*)&locals;
2129
+ #{@locals_struct} *plocals = malloc(sizeof(typeof(*plocals)));
1725
2130
  #{@frame_struct} frame;
1726
2131
  #{@frame_struct} *pframe;
1727
2132
 
1728
2133
  frame.plocals = plocals;
1729
2134
  frame.parent_frame = (void*)_parent_frame;
2135
+ frame.stack_chunk = ((typeof(pframe))_parent_frame)->stack_chunk;
1730
2136
  frame.return_value = Qnil;
1731
2137
  frame.target_frame = &frame;
1732
2138
  frame.exception = Qnil;
1733
2139
  frame.rescue = 0;
1734
2140
 
1735
- locals.pframe = &frame;
2141
+ plocals->pframe = LONG2FIX(&frame);
1736
2142
 
1737
2143
  pframe = (void*)&frame;
1738
2144
 
@@ -1742,10 +2148,6 @@ module FastRuby
1742
2148
  int aux = setjmp(pframe->jmp);
1743
2149
  if (aux != 0) {
1744
2150
 
1745
- if (pframe->target_frame == (void*)-2) {
1746
- return pframe->return_value;
1747
- }
1748
-
1749
2151
  if (pframe->target_frame != pframe) {
1750
2152
  // raise exception
1751
2153
  ((typeof(pframe))_parent_frame)->exception = pframe->exception;
@@ -1757,7 +2159,7 @@ module FastRuby
1757
2159
  return plocals->return_value;
1758
2160
  }
1759
2161
 
1760
- locals.self = self;
2162
+ plocals->self = self;
1761
2163
  "
1762
2164
  end
1763
2165
 
@@ -1932,6 +2334,8 @@ module FastRuby
1932
2334
  }
1933
2335
  }
1934
2336
 
2337
+ if (address==0) convention = #{literal_value :ruby};
2338
+
1935
2339
  #{convention_global_name ? convention_global_name + " = 0;" : ""}
1936
2340
  if (recvtype != Qnil) {
1937
2341
 
@@ -2014,9 +2418,11 @@ module FastRuby
2014
2418
 
2015
2419
  parent_frame = (void*)param;
2016
2420
 
2421
+ frame.stack_chunk = parent_frame->stack_chunk;
2017
2422
  frame.parent_frame = (void*)param;
2018
2423
  frame.plocals = parent_frame->plocals;
2019
2424
  frame.target_frame = &frame;
2425
+ frame.exception = Qnil;
2020
2426
  frame.rescue = #{rescued ? rescued : "parent_frame->rescue"};
2021
2427
 
2022
2428
  plocals = frame.plocals;
@@ -2036,6 +2442,7 @@ module FastRuby
2036
2442
  pframe->exception = original_frame->exception;
2037
2443
  pframe->target_frame = original_frame->target_frame;
2038
2444
  pframe->return_value = original_frame->return_value;
2445
+
2039
2446
  longjmp(pframe->jmp,1);
2040
2447
  }
2041
2448