fastruby 0.0.14 → 0.0.15

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.
@@ -49,8 +49,6 @@ module FastRuby
49
49
  mobject = nil
50
50
  len = nil
51
51
 
52
- extra_inference = {}
53
-
54
52
  if recvtype
55
53
 
56
54
  inference_complete = true
@@ -64,31 +62,6 @@ module FastRuby
64
62
  inference_complete = false
65
63
  end
66
64
  end
67
-
68
- if recvtype.respond_to? :fastruby_method and inference_complete
69
- method_tree = nil
70
- begin
71
- method_tree = recvtype.instance_method(call_tree[2]).fastruby.tree
72
- rescue NoMethodError
73
- end
74
-
75
- if method_tree
76
- mobject = recvtype.build(signature, call_tree[2])
77
- yield_signature = mobject.yield_signature
78
-
79
- if not args_tree
80
- elsif args_tree.first == :lasgn
81
- if yield_signature[0]
82
- extra_inference[args_tree.last] = yield_signature[0]
83
- end
84
- elsif args_tree.first == :masgn
85
- yield_args = args_tree[1][1..-1].map(&:last)
86
- (0...yield_signature.size-1).each do |i|
87
- extra_inference[yield_args[i]] = yield_signature[i]
88
- end
89
- end
90
- end
91
- end
92
65
  end
93
66
 
94
67
  anonymous_impl = tree[3]
@@ -103,8 +76,6 @@ module FastRuby
103
76
 
104
77
  str_impl = ""
105
78
 
106
- with_extra_inference(extra_inference) do
107
-
108
79
  on_block do
109
80
  # if impl_tree is a block, implement the last node with a return
110
81
  if anonymous_impl
@@ -129,18 +100,41 @@ module FastRuby
129
100
  str_impl = "last_expression = Qnil;"
130
101
  end
131
102
  end
132
- end
133
-
134
103
 
135
104
  if not args_tree
136
- str_arg_initialization = ""
137
105
  elsif args_tree.first == :lasgn
138
- str_arg_initialization = "plocals->#{args_tree[1]} = arg;"
106
+ str_arg_initialization << "plocals->#{args_tree[1]} = arg;"
139
107
  elsif args_tree.first == :masgn
140
- arguments = args_tree[1][1..-1].map(&:last)
141
-
108
+
109
+ str_arg_initialization << "
110
+ {
111
+ if (TYPE(arg) != T_ARRAY) {
112
+ if (arg != Qnil) {
113
+ arg = rb_ary_new4(1,&arg);
114
+ } else {
115
+ arg = rb_ary_new2(0);
116
+ }
117
+ } else if (RARRAY(arg)->len <= 1) {
118
+ arg = rb_ary_new4(1,&arg);
119
+ }
120
+ }
121
+ "
122
+
123
+ arguments = args_tree[1][1..-1]
124
+
142
125
  (0..arguments.size-1).each do |i|
143
- str_arg_initialization << "plocals->#{arguments[i]} = rb_ary_entry(arg,#{i});\n"
126
+ arg = arguments[i]
127
+ if arg[0] == :lasgn
128
+ str_arg_initialization << "plocals->#{arguments[i].last} = rb_ary_entry(arg,#{i});\n"
129
+ elsif arg[0] == :splat
130
+ str_arg_initialization << "plocals->#{arg.last.last} = rb_ary_new2(RARRAY(arg)->len-#{i});\n
131
+
132
+ int i;
133
+ for (i=#{i};i<RARRAY(arg)->len;i++){
134
+ rb_ary_store(plocals->#{arg.last.last},i-#{i},rb_ary_entry(arg,i));
135
+ }
136
+ "
137
+ end
144
138
  end
145
139
  end
146
140
  rb_funcall_caller_code = nil
@@ -339,7 +333,7 @@ module FastRuby
339
333
  rb_raise(rb_eLocalJumpError,\"return from proc-closure\");
340
334
  } else {
341
335
  ((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
342
- rb_jump_tag(aux);
336
+ frb_jump_tag(aux);
343
337
  }
344
338
  } else {
345
339
  rb_raise(rb_eLocalJumpError, \"unexpected return\");
@@ -382,7 +376,7 @@ module FastRuby
382
376
  } else if (aux == FASTRUBY_TAG_REDO) {
383
377
  // do nothing and let execute the block again
384
378
  } else {
385
- rb_jump_tag(aux);
379
+ frb_jump_tag(aux);
386
380
  return frame.return_value;
387
381
  }
388
382
  }
@@ -396,6 +390,48 @@ module FastRuby
396
390
  "
397
391
  }
398
392
 
393
+ rb_funcall_block_code_callcc = proc { |name| "
394
+ static VALUE #{name}(VALUE arg, VALUE _plocals) {
395
+ // block for call to #{call_tree[2]}
396
+ VALUE last_expression = Qnil;
397
+
398
+ #{@frame_struct} frame;
399
+ #{@frame_struct} *pframe = (void*)&frame;
400
+ #{@locals_struct} *plocals = (void*)_plocals;
401
+
402
+ frame.plocals = plocals;
403
+ frame.parent_frame = 0;
404
+ frame.return_value = Qnil;
405
+ frame.rescue = 0;
406
+ frame.targetted = 0;
407
+ frame.thread_data = rb_current_thread_data();
408
+
409
+ int aux = setjmp(frame.jmp);
410
+ if (aux != 0) {
411
+
412
+ if (aux == FASTRUBY_TAG_NEXT) {
413
+ return pframe->thread_data->accumulator;
414
+ } else if (aux == FASTRUBY_TAG_REDO) {
415
+ // do nothing and let execute the block again
416
+ } else {
417
+ frb_jump_tag(aux);
418
+ return frame.return_value;
419
+ }
420
+ }
421
+
422
+ if (rb_obj_is_kind_of(arg,rb_cCont)) {
423
+ struct FASTRUBYTHREADDATA* thread_data = frame.thread_data;
424
+ rb_ivar_set(arg,#{intern_num :__stack_chunk},thread_data->rb_stack_chunk);
425
+ }
426
+
427
+ #{str_arg_initialization}
428
+ #{str_impl}
429
+
430
+ return last_expression;
431
+ }
432
+ "
433
+ }
434
+
399
435
 
400
436
  fastruby_str_arg_initialization = ""
401
437
 
@@ -404,10 +440,22 @@ module FastRuby
404
440
  elsif args_tree.first == :lasgn
405
441
  fastruby_str_arg_initialization = "plocals->#{args_tree[1]} = argv[0];"
406
442
  elsif args_tree.first == :masgn
407
- arguments = args_tree[1][1..-1].map(&:last)
408
-
443
+ arguments = args_tree[1][1..-1]
444
+
409
445
  (0..arguments.size-1).each do |i|
410
- fastruby_str_arg_initialization << "plocals->#{arguments[i]} = #{i} < argc ? argv[#{i}] : Qnil;\n"
446
+ arg = arguments[i]
447
+ if arg[0] == :lasgn
448
+ fastruby_str_arg_initialization << "plocals->#{arg.last} = #{i} < argc ? argv[#{i}] : Qnil;\n"
449
+ elsif arg[0] == :splat
450
+ fastruby_str_arg_initialization << "plocals->#{arg.last.last} = rb_ary_new2(#{arguments.size-1-i});\n
451
+ {
452
+ int i;
453
+ for (i=#{i};i<argc;i++){
454
+ rb_ary_store(plocals->#{arg.last.last},i-#{i},argv[i]);
455
+ }
456
+ }
457
+ "
458
+ end
411
459
  end
412
460
  end
413
461
 
@@ -496,16 +544,55 @@ module FastRuby
496
544
  }
497
545
  "
498
546
 
547
+ precode = "
548
+ struct FASTRUBYTHREADDATA* thread_data = 0;
549
+ VALUE saved_rb_stack_chunk = Qnil;
550
+
551
+ pframe->next_recv = #{recv_tree ? to_c(recv_tree) : "plocals->self"};
552
+
553
+ NODE* node = rb_method_node(CLASS_OF(pframe->next_recv), #{intern_num mname});
554
+
555
+ if (node == #{@callcc_node_gvar}) {
556
+
557
+ // freeze all stacks
558
+ thread_data = rb_current_thread_data();
559
+
560
+ if (thread_data != 0) {
561
+ VALUE rb_stack_chunk = thread_data->rb_stack_chunk;
562
+ saved_rb_stack_chunk = rb_stack_chunk;
563
+
564
+ // freeze the complete chain of stack chunks
565
+ while (rb_stack_chunk != Qnil) {
566
+ struct STACKCHUNK* stack_chunk;
567
+ Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
568
+
569
+ stack_chunk_freeze(stack_chunk);
570
+
571
+ rb_stack_chunk = rb_ivar_get(rb_stack_chunk,#{intern_num :_parent_stack_chunk});
572
+ }
573
+ }
574
+ }
575
+ "
576
+
577
+ postcode = "
578
+ if (node == #{@callcc_node_gvar}) {
579
+ thread_data->rb_stack_chunk = saved_rb_stack_chunk;
580
+ }
581
+ "
582
+
583
+
499
584
  funcall_call_code = "
500
585
  return #{
501
586
  frame_call(
502
587
  protected_block(inline_block("
503
-
504
- pframe->next_recv = #{recv_tree ? to_c(recv_tree) : "plocals->self"};
505
-
588
+
506
589
  NODE* node = rb_method_node(CLASS_OF(pframe->next_recv), #{intern_num mname});
507
590
  void* caller_func;
508
591
  void* block_func;
592
+ typeof(plocals) current_plocals;
593
+
594
+ if (pframe->thread_data == 0) pframe->thread_data = rb_current_thread_data();
595
+ void* last_plocals = pframe->thread_data->last_plocals;
509
596
 
510
597
  if (
511
598
  node == #{@proc_node_gvar} ||
@@ -517,18 +604,44 @@ module FastRuby
517
604
  } else if (node == #{@procnew_node_gvar} && pframe->next_recv == rb_cProc) {
518
605
  caller_func = #{anonymous_function(&rb_funcall_caller_code_with_lambda)};
519
606
  block_func = #{anonymous_function(&rb_funcall_block_code_proc_new)};
607
+ } else if (node == #{@callcc_node_gvar}) {
608
+ caller_func = #{anonymous_function(&rb_funcall_caller_code)};
609
+ block_func = #{anonymous_function(&rb_funcall_block_code_callcc)};
520
610
  } else {
521
611
  caller_func = #{anonymous_function(&rb_funcall_caller_code)};
522
612
  block_func = #{anonymous_function(&rb_funcall_block_code)};
523
613
  }
614
+
524
615
 
525
- return rb_iterate(
616
+ VALUE ret = rb_iterate(
526
617
  caller_func,
527
618
  (VALUE)pframe,
528
619
  block_func,
529
620
  (VALUE)plocals);
530
621
 
531
- "), true)
622
+ if (node == #{@callcc_node_gvar}) {
623
+
624
+ // remove active flags of abandoned stack
625
+ current_plocals = pframe->thread_data->last_plocals;
626
+ while (current_plocals) {
627
+ current_plocals->active = Qfalse;
628
+ current_plocals = (typeof(current_plocals))FIX2LONG(current_plocals->parent_locals);
629
+ }
630
+
631
+ // restore last_plocals
632
+ pframe->thread_data->last_plocals = last_plocals;
633
+
634
+ // mark all scopes as active
635
+ current_plocals = last_plocals;
636
+
637
+ while (current_plocals) {
638
+ current_plocals->active = Qtrue;
639
+ current_plocals = (typeof(current_plocals))FIX2LONG(current_plocals->parent_locals);
640
+ }
641
+ }
642
+
643
+ return ret;
644
+ "), true), precode, postcode
532
645
  )
533
646
  };
534
647
  "
@@ -112,6 +112,10 @@ private
112
112
 
113
113
  plocals = (typeof(plocals))stack_chunk_alloc(stack_chunk ,sizeof(typeof(*plocals))/sizeof(void*));
114
114
 
115
+ plocals->parent_locals = LONG2FIX(frame.thread_data->last_plocals);
116
+ void* old_parent_locals = frame.thread_data->last_plocals;
117
+ frame.thread_data->last_plocals = plocals;
118
+
115
119
  frame.plocals = plocals;
116
120
  plocals->active = Qtrue;
117
121
  plocals->self = self;
@@ -128,6 +132,9 @@ private
128
132
  }
129
133
 
130
134
  plocals->active = Qfalse;
135
+
136
+ frame.thread_data->last_plocals = old_parent_locals;
137
+
131
138
  return Qnil;
132
139
  }
133
140
  "