fastruby 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -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