fastruby 0.0.14 → 0.0.15

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