fastruby 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -18,34 +18,32 @@ you should have received a copy of the gnu general public license
18
18
  along with fastruby. if not, see <http://www.gnu.org/licenses/>.
19
19
 
20
20
  =end
21
- require "rubygems"
22
- require "inline"
23
21
  require "set"
24
22
  require "fastruby/method_extension"
23
+ require "fastruby/set_tree"
24
+ require "fastruby/exceptions"
25
+ require "rubygems"
26
+ require "sexp"
25
27
 
26
28
  module FastRuby
27
29
  class Context
28
-
29
- class UnwindFastrubyFrame < Exception
30
- def initialize(ex,target_frame,return_value)
31
- @ex = ex
32
- @target_frame = target_frame
33
- @return_value = return_value
34
- end
35
- end
36
-
37
30
  attr_accessor :infer_lvar_map
38
31
  attr_accessor :alt_method_name
39
32
  attr_accessor :locals
40
33
  attr_accessor :options
41
34
  attr_accessor :infer_self
35
+ attr_accessor :snippet_hash
36
+ attr_reader :no_cache
37
+ attr_reader :init_extra
42
38
  attr_reader :extra_code
43
39
  attr_reader :yield_signature
44
40
 
45
41
  def initialize(common_func = true)
46
42
  @infer_lvar_map = Hash.new
43
+ @no_cache = false
47
44
  @extra_code = ""
48
45
  @options = {}
46
+ @init_extra = Array.new
49
47
  @frame_struct = "struct {
50
48
  void* parent_frame;
51
49
  void* target_frame;
@@ -62,9 +60,20 @@ module FastRuby
62
60
  void* block_function_param;
63
61
  }"
64
62
 
63
+
65
64
  extra_code << '#include "node.h"
66
65
  '
67
66
 
67
+ ruby_code = "
68
+ $LOAD_PATH << #{FastRuby.fastruby_load_path.inspect}
69
+ require #{FastRuby.fastruby_script_path.inspect}
70
+ "
71
+
72
+ init_extra << "
73
+ rb_eval_string(#{ruby_code.inspect});
74
+ "
75
+
76
+ @common_func = common_func
68
77
  if common_func
69
78
  extra_code << "static VALUE _rb_gvar_set(void* ge,VALUE value) {
70
79
  rb_gvar_set((struct global_entry*)ge,value);
@@ -72,6 +81,10 @@ module FastRuby
72
81
  }
73
82
  "
74
83
 
84
+ 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));
86
+ }"
87
+
75
88
  extra_code << "static VALUE _rb_ivar_set(VALUE recv,ID idvar, VALUE value) {
76
89
  rb_ivar_set(recv,idvar,value);
77
90
  return value;
@@ -82,6 +95,11 @@ module FastRuby
82
95
  *destination = value;
83
96
  return value;
84
97
  }
98
+
99
+ /*
100
+ #{caller.join("\n")}
101
+ */
102
+
85
103
  "
86
104
  end
87
105
  end
@@ -125,6 +143,8 @@ module FastRuby
125
143
  other_call_tree = call_tree.dup
126
144
  other_call_tree[1] = s(:lvar, :arg)
127
145
 
146
+ mname = call_tree[2]
147
+
128
148
  call_args_tree = call_tree[3]
129
149
 
130
150
  caller_code = nil
@@ -135,8 +155,6 @@ module FastRuby
135
155
  mobject = nil
136
156
  len = nil
137
157
 
138
- convention = :ruby
139
-
140
158
  extra_inference = {}
141
159
 
142
160
  if recvtype
@@ -153,10 +171,7 @@ module FastRuby
153
171
  end
154
172
  end
155
173
 
156
- convention = nil
157
-
158
174
  if recvtype.respond_to? :fastruby_method and inference_complete
159
-
160
175
  method_tree = nil
161
176
  begin
162
177
  method_tree = recvtype.instance_method(call_tree[2]).fastruby.tree
@@ -178,24 +193,8 @@ module FastRuby
178
193
  extra_inference[yield_args[i]] = yield_signature[i]
179
194
  end
180
195
  end
181
-
182
- convention = :fastruby
183
- else
184
- mobject = recvtype.instance_method(call_tree[2])
185
- convention = :cruby
186
196
  end
187
- else
188
- mobject = recvtype.instance_method(call_tree[2])
189
- convention = :cruby
190
- end
191
-
192
- address = getaddress(mobject)
193
- len = getlen(mobject)
194
-
195
- unless address
196
- convention = :ruby
197
197
  end
198
-
199
198
  end
200
199
 
201
200
  anonymous_impl = tree[3]
@@ -238,7 +237,19 @@ module FastRuby
238
237
  end
239
238
  end
240
239
 
241
- if convention == :ruby or convention == :cruby
240
+
241
+ if not args_tree
242
+ str_arg_initialization = ""
243
+ elsif args_tree.first == :lasgn
244
+ str_arg_initialization = "plocals->#{args_tree[1]} = arg;"
245
+ elsif args_tree.first == :masgn
246
+ arguments = args_tree[1][1..-1].map(&:last)
247
+
248
+ (0..arguments.size-1).each do |i|
249
+ str_arg_initialization << "plocals->#{arguments[i]} = rb_ary_entry(arg,#{i});\n"
250
+ end
251
+ end
252
+ rb_funcall_caller_code = nil
242
253
 
243
254
  if call_args_tree.size > 1
244
255
 
@@ -247,12 +258,12 @@ module FastRuby
247
258
 
248
259
  str_recv = "plocals->self" unless recv_tree
249
260
 
250
- caller_code = proc { |name| "
261
+ rb_funcall_caller_code = proc { |name| "
251
262
  static VALUE #{name}(VALUE param) {
252
263
  // call to #{call_tree[2]}
253
264
 
254
265
  #{str_lvar_initialization}
255
- return rb_funcall(#{str_recv}, #{call_tree[2].to_i}, #{call_args_tree.size-1}, #{str_called_code_args});
266
+ return rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, #{call_args_tree.size-1}, #{str_called_code_args});
256
267
  }
257
268
  "
258
269
  }
@@ -261,31 +272,18 @@ module FastRuby
261
272
  str_recv = to_c recv_tree
262
273
  str_recv = "plocals->self" unless recv_tree
263
274
 
264
- caller_code = proc { |name| "
275
+ rb_funcall_caller_code = proc { |name| "
265
276
  static VALUE #{name}(VALUE param) {
266
277
  // call to #{call_tree[2]}
267
278
  #{str_lvar_initialization}
268
- return rb_funcall(#{str_recv}, #{call_tree[2].to_i}, 0);
279
+ return rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, 0);
269
280
  }
270
281
  "
271
282
  }
272
283
  end
273
284
 
274
- if not args_tree
275
- str_arg_initialization = ""
276
- elsif args_tree.first == :lasgn
277
- str_arg_initialization = "plocals->#{args_tree[1]} = arg;"
278
- elsif args_tree.first == :masgn
279
- arguments = args_tree[1][1..-1].map(&:last)
280
-
281
- (0..arguments.size-1).each do |i|
282
- str_arg_initialization << "plocals->#{arguments[i]} = rb_ary_entry(arg,#{i});\n"
283
- end
284
- end
285
-
286
- str_arg_initialization
287
285
 
288
- block_code = proc { |name| "
286
+ rb_funcall_block_code = proc { |name| "
289
287
  static VALUE #{name}(VALUE arg, VALUE _plocals) {
290
288
  // block for call to #{call_tree[2]}
291
289
  VALUE last_expression = Qnil;
@@ -308,15 +306,15 @@ module FastRuby
308
306
  }
309
307
 
310
308
  VALUE ex = rb_funcall(
311
- (VALUE)#{UnwindFastrubyFrame.internal_value},
312
- #{:new.to_i},
309
+ #{literal_value FastRuby::Context::UnwindFastrubyFrame},
310
+ #{intern_num :new},
313
311
  3,
314
312
  pframe->exception,
315
313
  LONG2FIX(pframe->target_frame),
316
314
  pframe->return_value
317
315
  );
318
316
 
319
- rb_funcall(plocals->self, #{:raise.to_i}, 1, ex);
317
+ rb_funcall(plocals->self, #{intern_num :raise}, 1, ex);
320
318
  }
321
319
  return frame.return_value;
322
320
  }
@@ -330,21 +328,18 @@ module FastRuby
330
328
  "
331
329
  }
332
330
 
333
- protected_block("rb_iterate(#{anonymous_function(&caller_code)}, (VALUE)pframe, #{anonymous_function(&block_code)}, (VALUE)plocals)", true)
334
-
335
- elsif convention == :fastruby
336
331
 
337
- str_arg_initialization = ""
332
+ fastruby_str_arg_initialization = ""
338
333
 
339
334
  if not args_tree
340
- str_arg_initialization = ""
335
+ fastruby_str_arg_initialization = ""
341
336
  elsif args_tree.first == :lasgn
342
- str_arg_initialization = "plocals->#{args_tree[1]} = argv[0];"
337
+ fastruby_str_arg_initialization = "plocals->#{args_tree[1]} = argv[0];"
343
338
  elsif args_tree.first == :masgn
344
339
  arguments = args_tree[1][1..-1].map(&:last)
345
340
 
346
341
  (0..arguments.size-1).each do |i|
347
- str_arg_initialization << "plocals->#{arguments[i]} = #{i} < argc ? argv[#{i}] : Qnil;\n"
342
+ fastruby_str_arg_initialization << "plocals->#{arguments[i]} = #{i} < argc ? argv[#{i}] : Qnil;\n"
348
343
  end
349
344
  end
350
345
 
@@ -380,7 +375,7 @@ module FastRuby
380
375
 
381
376
  }
382
377
 
383
- #{str_arg_initialization}
378
+ #{fastruby_str_arg_initialization}
384
379
  #{str_impl}
385
380
 
386
381
  return last_expression;
@@ -388,16 +383,17 @@ module FastRuby
388
383
  "
389
384
  }
390
385
 
391
-
392
386
  str_recv = "plocals->self"
393
387
 
394
388
  if recv_tree
395
389
  str_recv = to_c recv_tree
396
390
  end
397
391
 
392
+ caller_code = nil
393
+ convention_global_name = add_global_name("int",0)
394
+
398
395
  if call_args_tree.size > 1
399
- value_cast = ( ["VALUE"]*(call_tree[3].size) ).join(",")
400
- value_cast = value_cast + ", VALUE, VALUE" if convention == :fastruby
396
+ value_cast = ( ["VALUE"]*(call_tree[3].size) ).join(",") + ", VALUE, VALUE"
401
397
 
402
398
  str_called_code_args = call_tree[3][1..-1].map{|subtree| to_c subtree}.join(",")
403
399
 
@@ -411,7 +407,7 @@ module FastRuby
411
407
 
412
408
  // call to #{call_tree[2]}
413
409
 
414
- return ((VALUE(*)(#{value_cast}))0x#{address.to_s(16)})(#{str_recv}, (VALUE)&block, (VALUE)pframe, #{str_called_code_args});
410
+ 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});
415
411
  }
416
412
  "
417
413
  }
@@ -427,14 +423,21 @@ module FastRuby
427
423
 
428
424
  // call to #{call_tree[2]}
429
425
 
430
- return ((VALUE(*)(VALUE,VALUE,VALUE))0x#{address.to_s(16)})(#{str_recv}, (VALUE)&block, (VALUE)pframe);
426
+ return ((VALUE(*)(VALUE,VALUE,VALUE))#{encode_address(recvtype,signature,mname,call_tree,inference_complete,convention_global_name)})(#{str_recv}, (VALUE)&block, (VALUE)pframe);
431
427
  }
432
428
  "
433
429
  }
434
430
  end
435
431
 
436
- "#{anonymous_function(&caller_code)}((VALUE)plocals, (VALUE)pframe)"
437
- end
432
+ inline_block "
433
+ if (#{convention_global_name}) {
434
+ return #{anonymous_function(&caller_code)}((VALUE)plocals, (VALUE)pframe);
435
+ } else {
436
+ return #{
437
+ protected_block("rb_iterate(#{anonymous_function(&rb_funcall_caller_code)}, (VALUE)pframe, #{anonymous_function(&rb_funcall_block_code)}, (VALUE)plocals)", true)
438
+ };
439
+ }
440
+ "
438
441
  end
439
442
 
440
443
  def to_c_yield(tree)
@@ -478,7 +481,7 @@ module FastRuby
478
481
  anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){})"
479
482
  end
480
483
 
481
- protected_block(ret, true)
484
+ protected_block(ret, false)
482
485
  end
483
486
 
484
487
  def to_c_block(tree)
@@ -518,7 +521,7 @@ module FastRuby
518
521
  else
519
522
  inline_block("
520
523
  pframe->target_frame = (void*)-1;
521
- pframe->exception = (VALUE)#{LocalJumpError.exception.internal_value};
524
+ pframe->exception = #{literal_value LocalJumpError.exception};
522
525
  longjmp(pframe->jmp,1);
523
526
  return Qnil;
524
527
  ")
@@ -532,7 +535,7 @@ module FastRuby
532
535
  else
533
536
  inline_block("
534
537
  pframe->target_frame = (void*)-1;
535
- pframe->exception = (VALUE)#{LocalJumpError.exception.internal_value};
538
+ pframe->exception = #{literal_value LocalJumpError.exception};
536
539
  longjmp(pframe->jmp,1);
537
540
  return Qnil;
538
541
  ")
@@ -541,7 +544,7 @@ module FastRuby
541
544
  end
542
545
 
543
546
  def to_c_lit(tree)
544
- "(VALUE)#{tree[1].internal_value}"
547
+ literal_value tree[1]
545
548
  end
546
549
 
547
550
  def to_c_nil(tree)
@@ -549,7 +552,7 @@ module FastRuby
549
552
  end
550
553
 
551
554
  def to_c_str(tree)
552
- "(VALUE)#{tree[1].internal_value}"
555
+ literal_value tree[1]
553
556
  end
554
557
 
555
558
  def to_c_hash(tree)
@@ -597,24 +600,24 @@ module FastRuby
597
600
  inline_block "
598
601
  // set constant #{tree[1].to_s}
599
602
  VALUE val = #{to_c tree[2]};
600
- rb_const_set(rb_cObject, #{tree[1].to_i}, val);
603
+ rb_const_set(rb_cObject, #{intern_num tree[1]}, val);
601
604
  return val;
602
605
  "
603
- elsif tree[1].instance_of? Sexp
606
+ elsif tree[1].instance_of? FastRuby::FastRubySexp
604
607
 
605
608
  if tree[1].node_type == :colon2
606
609
  inline_block "
607
610
  // set constant #{tree[1].to_s}
608
611
  VALUE val = #{to_c tree[2]};
609
612
  VALUE klass = #{to_c tree[1][1]};
610
- rb_const_set(klass, #{tree[1][2].to_i}, val);
613
+ rb_const_set(klass, #{intern_num tree[1][2]}, val);
611
614
  return val;
612
615
  "
613
616
  elsif tree[1].node_type == :colon3
614
617
  inline_block "
615
618
  // set constant #{tree[1].to_s}
616
619
  VALUE val = #{to_c tree[2]};
617
- rb_const_set(rb_cObject, #{tree[1][1].to_i}, val);
620
+ rb_const_set(rb_cObject, #{intern_num tree[1][1]}, val);
618
621
  return val;
619
622
  "
620
623
  end
@@ -652,11 +655,165 @@ module FastRuby
652
655
  end
653
656
 
654
657
  def to_c_const(tree)
655
- "rb_const_get(CLASS_OF(plocals->self), #{tree[1].to_i})"
658
+ "rb_const_get(CLASS_OF(plocals->self), #{intern_num(tree[1])})"
656
659
  end
657
660
 
658
661
  def to_c_defn(tree)
659
- "rb_funcall(plocals->self,#{:fastruby.to_i},1,(VALUE)#{tree.internal_value})"
662
+
663
+ method_name = tree[1]
664
+ args_tree = tree[2]
665
+
666
+ global_klass_variable = add_global_name("VALUE", "Qnil");
667
+
668
+ hash = Hash.new
669
+ value_cast = ( ["VALUE"]*(args_tree.size+2) ).join(",")
670
+
671
+ strmethodargs = ""
672
+ strmethodargs_class = (["self"] + args_tree[1..-1]).map{|arg| "CLASS_OF(#{arg.to_s})"}.join(",")
673
+
674
+ if args_tree.size > 1
675
+ strmethodargs = "self,block,(VALUE)&frame,#{args_tree[1..-1].map(&:to_s).join(",") }"
676
+ else
677
+ strmethodargs = "self,block,(VALUE)&frame"
678
+ end
679
+
680
+ strmethod_signature = (["self"] + args_tree[1..-1]).map { |arg|
681
+ "sprintf(method_name+strlen(method_name), \"%lu\", FIX2LONG(rb_obj_id(CLASS_OF(#{arg}))));\n"
682
+ }.join
683
+
684
+ anonymous_method_name = anonymous_function{ |anonymous_method_name| "VALUE #{anonymous_method_name}(#{(["self"]+args_tree[1..-1]).map{|arg| "VALUE #{arg}" }.join(",")}) {
685
+
686
+ VALUE klass = #{global_klass_variable};
687
+ char method_name[0x100];
688
+
689
+ method_name[0] = '_';
690
+ method_name[1] = 0;
691
+
692
+ sprintf(method_name+1, \"#{method_name}\");
693
+ #{strmethod_signature}
694
+
695
+ NODE* body;
696
+ ID id;
697
+
698
+ id = rb_intern(method_name);
699
+ body = rb_method_node(klass,id);
700
+
701
+ if (body == 0) {
702
+ VALUE argv_class[] = {#{strmethodargs_class} };
703
+ VALUE signature = rb_ary_new4(#{args_tree.size},argv_class);
704
+
705
+ VALUE mobject = rb_funcall(#{global_klass_variable}, #{intern_num :build}, 2, signature,rb_str_new2(#{method_name.to_s.inspect}));
706
+
707
+ struct METHOD {
708
+ VALUE klass, rklass;
709
+ VALUE recv;
710
+ ID id, oid;
711
+ int safe_level;
712
+ NODE *body;
713
+ };
714
+
715
+ struct METHOD *data;
716
+ Data_Get_Struct(mobject, struct METHOD, data);
717
+ body = data->body;
718
+
719
+ if (body == 0) {
720
+ rb_raise(rb_eRuntimeError,\"method not found after build: '%s'\", method_name);
721
+ }
722
+ }
723
+
724
+ if (nd_type(body) == NODE_CFUNC) {
725
+ struct {
726
+ void* parent_frame;
727
+ void* target_frame;
728
+ void* plocals;
729
+ jmp_buf jmp;
730
+ VALUE return_value;
731
+ VALUE exception;
732
+ int rescue;
733
+ } frame;
734
+
735
+ frame.target_frame = 0;
736
+ frame.parent_frame = 0;
737
+ frame.rescue = 0;
738
+ frame.exception = Qnil;
739
+ frame.return_value = Qnil;
740
+
741
+ int argc = body->nd_argc;
742
+
743
+ VALUE block = Qfalse;
744
+
745
+ if (rb_block_given_p()) {
746
+ struct {
747
+ void *block_function_address;
748
+ void *block_function_param;
749
+ } block_struct;
750
+
751
+ block_struct.block_function_address = re_yield;
752
+ block_struct.block_function_param = 0;
753
+
754
+ block = (VALUE)&block_struct;
755
+ }
756
+
757
+ int aux = setjmp(frame.jmp);
758
+ if (aux != 0) {
759
+ if (frame.target_frame == (void*)-1) {
760
+ rb_funcall(self, #{intern_num :raise}, 1, frame.exception);
761
+ }
762
+
763
+ if (frame.target_frame != &frame) {
764
+ VALUE ex = rb_funcall(
765
+ #{literal_value FastRuby::Context::UnwindFastrubyFrame},
766
+ #{intern_num :new},
767
+ 3,
768
+ frame.exception,
769
+ LONG2FIX(frame.target_frame),
770
+ frame.return_value
771
+ );
772
+
773
+ rb_funcall(self, #{intern_num :raise}, 1, ex);
774
+ }
775
+
776
+ return Qnil;
777
+ }
778
+
779
+ if (argc == #{args_tree.size+1}) {
780
+ return ((VALUE(*)(#{value_cast}))body->nd_cfnc)(#{strmethodargs});
781
+ } else if (argc == -1) {
782
+ VALUE argv[] = {#{(["block,(VALUE)&frame"]+args_tree[1..-1]).map(&:to_s).join(",")} };
783
+ return ((VALUE(*)(int,VALUE*,VALUE))body->nd_cfnc)(#{args_tree.size},argv,self);
784
+ } else if (argc == -2) {
785
+ VALUE argv[] = {#{(["block,(VALUE)&frame"]+args_tree[1..-1]).map(&:to_s).join(",")} };
786
+ return ((VALUE(*)(VALUE,VALUE))body->nd_cfnc)(self, rb_ary_new4(#{args_tree.size},argv));
787
+ } else {
788
+ rb_raise(rb_eArgError, \"wrong number of arguments (#{args_tree.size-1} for %d)\", argc);
789
+ }
790
+ }
791
+
792
+ return Qnil;
793
+ }"
794
+ }
795
+
796
+ alt_options = options.dup
797
+
798
+ alt_options.delete(:self)
799
+ alt_options.delete(:main)
800
+
801
+ inline_block "
802
+ #{global_klass_variable} = plocals->self;
803
+
804
+ // set tree
805
+ rb_funcall(#{literal_value FastRuby}, #{intern_num :set_tree}, 5,
806
+ #{global_klass_variable},
807
+ rb_str_new2(#{method_name.to_s.inspect}),
808
+ #{literal_value tree},
809
+ #{literal_value snippet_hash},
810
+ #{literal_value alt_options}
811
+
812
+ );
813
+
814
+ rb_define_method(plocals->self, #{method_name.to_s.inspect}, #{anonymous_method_name}, #{args_tree.size-1} );
815
+ "
816
+
660
817
  end
661
818
 
662
819
  def to_c_defs(tree)
@@ -665,6 +822,7 @@ module FastRuby
665
822
  tmp = FastRuby.build_defs(tree)
666
823
 
667
824
  extra_code << tmp[0]
825
+ @init_extra = @init_extra + tmp[2]
668
826
 
669
827
  inline_block "
670
828
  rb_define_singleton_method(#{to_c tree[1]}, \"#{tree[2].to_s}\", (void*)#{tmp[1]}, #{args_tree.size-1});
@@ -686,15 +844,15 @@ module FastRuby
686
844
  elsif nt == :lvar
687
845
  'rb_str_new2("local-variable")'
688
846
  elsif nt == :gvar
689
- "rb_gvar_defined((struct global_entry*)0x#{global_entry(tree[1][1]).to_s(16)}) ? #{"global-variable".internal_value} : Qnil"
847
+ "rb_gvar_defined((struct global_entry*)#{global_entry(tree[1][1])}) ? #{literal_value "global-variable"} : Qnil"
690
848
  elsif nt == :const
691
- "rb_const_defined(rb_cObject, #{tree[1][1].to_i}) ? #{"constant".internal_value} : Qnil"
849
+ "rb_const_defined(rb_cObject, #{intern_num tree[1][1]}) ? #{literal_value "constant"} : Qnil"
692
850
  elsif nt == :call
693
- "rb_method_node(CLASS_OF(#{to_c tree[1][1]}), #{tree[1][2].to_i}) ? #{"method".internal_value} : Qnil"
851
+ "rb_method_node(CLASS_OF(#{to_c tree[1][1]}), #{intern_num tree[1][2]}) ? #{literal_value "method"} : Qnil"
694
852
  elsif nt == :yield
695
- "rb_block_given_p() ? #{"yield".internal_value} : Qnil"
853
+ "rb_block_given_p() ? #{literal_value "yield"} : Qnil"
696
854
  elsif nt == :ivar
697
- "rb_ivar_defined(plocals->self,#{tree[1][1].to_i}) ? #{"instance-variable".internal_value} : Qnil"
855
+ "rb_ivar_defined(plocals->self,#{intern_num tree[1][1]}) ? #{literal_value "instance-variable"} : Qnil"
698
856
  elsif nt == :attrset or
699
857
  nt == :op_asgn1 or
700
858
  nt == :op_asgn2 or
@@ -710,9 +868,9 @@ module FastRuby
710
868
  nt == :cdecl or
711
869
  nt == :cvdecl or
712
870
  nt == :cvasgn
713
- "assignment".internal_value
871
+ literal_value "assignment"
714
872
  else
715
- "expression".internal_value
873
+ literal_value "expression"
716
874
  end
717
875
  end
718
876
 
@@ -726,6 +884,27 @@ module FastRuby
726
884
  #{@locals.map{|l| "VALUE #{l};\n"}.join}
727
885
  #{args_tree[1..-1].map{|arg| "VALUE #{arg};\n"}.join};
728
886
  }"
887
+
888
+ if @common_func
889
+ init_extra << "
890
+ #{@frame_struct} frame;
891
+ #{@locals_struct} locals;
892
+
893
+ locals.return_value = Qnil;
894
+ locals.pframe = &frame;
895
+ locals.self = rb_cObject;
896
+
897
+ frame.target_frame = 0;
898
+ frame.plocals = (void*)&locals;
899
+ frame.return_value = Qnil;
900
+ frame.exception = Qnil;
901
+ frame.rescue = 0;
902
+ frame.last_error = Qnil;
903
+
904
+ typeof(&frame) pframe = &frame;
905
+ "
906
+ end
907
+
729
908
  end
730
909
 
731
910
  def to_c_method_defs(tree)
@@ -800,7 +979,7 @@ module FastRuby
800
979
 
801
980
  int aux = setjmp(frame.jmp);
802
981
  if (aux != 0) {
803
- rb_funcall(self, #{:raise.to_i}, 1, frame.exception);
982
+ rb_funcall(self, #{intern_num :raise}, 1, frame.exception);
804
983
  }
805
984
 
806
985
 
@@ -809,39 +988,141 @@ module FastRuby
809
988
  "
810
989
  end
811
990
 
991
+ def add_main
992
+ if options[:main]
993
+
994
+ extra_code << "
995
+ static VALUE #{@alt_method_name}(VALUE self__);
996
+ static VALUE main_proc_call(VALUE self__, VALUE class_self_) {
997
+ #{@alt_method_name}(class_self_);
998
+ return Qnil;
999
+ }
1000
+
1001
+ "
1002
+
1003
+ init_extra << "
1004
+ {
1005
+ VALUE newproc = rb_funcall(rb_cObject,#{intern_num :new},0);
1006
+ rb_define_singleton_method(newproc, \"call\", main_proc_call, 1);
1007
+ rb_gv_set(\"$last_obj_proc\", newproc);
1008
+
1009
+ }
1010
+ "
1011
+ end
1012
+ end
1013
+
1014
+ def define_method_at_init(method_name, size, signature)
1015
+ init_extra << "
1016
+ {
1017
+ VALUE method_name = rb_funcall(
1018
+ #{literal_value FastRuby},
1019
+ #{intern_num :make_str_signature},
1020
+ 2,
1021
+ #{literal_value method_name},
1022
+ #{literal_value signature}
1023
+ );
1024
+
1025
+ rb_define_method(#{to_c s(:gvar, :$class_self)}, RSTRING(method_name)->ptr, #{alt_method_name}, #{size});
1026
+ }
1027
+ "
1028
+ end
1029
+
812
1030
  def to_c_method(tree)
813
1031
  method_name = tree[1]
814
1032
  args_tree = tree[2]
815
-
816
1033
  impl_tree = tree[3][1]
817
1034
 
818
- initialize_method_structs(args_tree)
1035
+ if (options[:main])
1036
+ initialize_method_structs(args_tree)
819
1037
 
820
- strargs = if args_tree.size > 1
821
- "VALUE block, VALUE _parent_frame, #{args_tree[1..-1].map{|arg| "VALUE #{arg}" }.join(",") }"
822
- else
823
- "VALUE block, VALUE _parent_frame"
824
- end
1038
+ strargs = if args_tree.size > 1
1039
+ "VALUE block, VALUE _parent_frame, #{args_tree[1..-1].map{|arg| "VALUE #{arg}" }.join(",") }"
1040
+ else
1041
+ "VALUE block, VALUE _parent_frame"
1042
+ end
825
1043
 
826
- "VALUE #{@alt_method_name || method_name}(#{strargs}) {
1044
+ ret = "VALUE #{@alt_method_name || method_name}() {
827
1045
 
828
- #{func_frame}
1046
+ #{@locals_struct} locals;
1047
+ #{@locals_struct} *plocals = (void*)&locals;
1048
+ #{@frame_struct} frame;
1049
+ #{@frame_struct} *pframe;
829
1050
 
830
- #{args_tree[1..-1].map { |arg|
831
- "locals.#{arg} = #{arg};\n"
832
- }.join("") }
1051
+ frame.plocals = plocals;
1052
+ frame.parent_frame = 0;
1053
+ frame.return_value = Qnil;
1054
+ frame.target_frame = &frame;
1055
+ frame.exception = Qnil;
1056
+ frame.rescue = 0;
1057
+
1058
+ locals.pframe = &frame;
1059
+
1060
+ pframe = (void*)&frame;
1061
+
1062
+ VALUE last_expression = Qnil;
1063
+
1064
+ int aux = setjmp(pframe->jmp);
1065
+ if (aux != 0) {
1066
+
1067
+ if (pframe->target_frame == (void*)-2) {
1068
+ return pframe->return_value;
1069
+ }
1070
+
1071
+ if (pframe->target_frame != pframe) {
1072
+ // raise exception
1073
+ return Qnil;
1074
+ }
1075
+
1076
+ return plocals->return_value;
1077
+ }
1078
+
1079
+ locals.self = self;
1080
+
1081
+ #{args_tree[1..-1].map { |arg|
1082
+ "locals.#{arg} = #{arg};\n"
1083
+ }.join("") }
833
1084
 
834
- pblock = (void*)block;
835
- if (pblock) {
836
- locals.block_function_address = pblock->block_function_address;
837
- locals.block_function_param = (VALUE)pblock->block_function_param;
838
- } else {
839
1085
  locals.block_function_address = 0;
840
1086
  locals.block_function_param = Qnil;
841
- }
842
1087
 
843
- return #{to_c impl_tree};
844
- }"
1088
+ return #{to_c impl_tree};
1089
+ }"
1090
+
1091
+ add_main
1092
+ ret
1093
+ else
1094
+
1095
+ initialize_method_structs(args_tree)
1096
+
1097
+ strargs = if args_tree.size > 1
1098
+ "VALUE block, VALUE _parent_frame, #{args_tree[1..-1].map{|arg| "VALUE #{arg}" }.join(",") }"
1099
+ else
1100
+ "VALUE block, VALUE _parent_frame"
1101
+ end
1102
+
1103
+ ret = "VALUE #{@alt_method_name || method_name}(#{strargs}) {
1104
+
1105
+ #{func_frame}
1106
+
1107
+ #{args_tree[1..-1].map { |arg|
1108
+ "locals.#{arg} = #{arg};\n"
1109
+ }.join("") }
1110
+
1111
+ pblock = (void*)block;
1112
+ if (pblock) {
1113
+ locals.block_function_address = pblock->block_function_address;
1114
+ locals.block_function_param = (VALUE)pblock->block_function_param;
1115
+ } else {
1116
+ locals.block_function_address = 0;
1117
+ locals.block_function_param = Qnil;
1118
+ }
1119
+
1120
+ return #{to_c impl_tree};
1121
+ }"
1122
+
1123
+ add_main
1124
+ ret
1125
+ end
845
1126
  end
846
1127
 
847
1128
  def locals_accessor
@@ -849,33 +1130,33 @@ module FastRuby
849
1130
  end
850
1131
 
851
1132
  def to_c_gvar(tree)
852
- "rb_gvar_get((struct global_entry*)0x#{global_entry(tree[1]).to_s(16)})"
1133
+ "rb_gvar_get((struct global_entry*)#{global_entry(tree[1])})"
853
1134
  end
854
1135
 
855
1136
  def to_c_gasgn(tree)
856
- "_rb_gvar_set((void*)0x#{global_entry(tree[1]).to_s(16)}, #{to_c tree[2]})"
1137
+ "_rb_gvar_set((void*)#{global_entry(tree[1])}, #{to_c tree[2]})"
857
1138
  end
858
1139
 
859
1140
  def to_c_ivar(tree)
860
- "rb_ivar_get(#{locals_accessor}self,#{tree[1].to_i})"
1141
+ "rb_ivar_get(#{locals_accessor}self,#{intern_num tree[1]})"
861
1142
  end
862
1143
 
863
1144
  def to_c_iasgn(tree)
864
- "_rb_ivar_set(#{locals_accessor}self,#{tree[1].to_i},#{to_c tree[2]})"
1145
+ "_rb_ivar_set(#{locals_accessor}self,#{intern_num tree[1]},#{to_c tree[2]})"
865
1146
  end
866
1147
 
867
1148
  def to_c_colon3(tree)
868
- "rb_const_get_from(rb_cObject, #{tree[1].to_i})"
1149
+ "rb_const_get_from(rb_cObject, #{intern_num tree[1]})"
869
1150
  end
870
1151
  def to_c_colon2(tree)
871
1152
  inline_block "
872
1153
  VALUE klass = #{to_c tree[1]};
873
1154
 
874
- if (rb_is_const_id(#{tree[2].to_i})) {
1155
+ if (rb_is_const_id(#{intern_num tree[2]})) {
875
1156
  switch (TYPE(klass)) {
876
1157
  case T_CLASS:
877
1158
  case T_MODULE:
878
- return rb_const_get_from(klass, #{tree[2].to_i});
1159
+ return rb_const_get_from(klass, #{intern_num tree[2]});
879
1160
  break;
880
1161
  default:
881
1162
  rb_raise(rb_eTypeError, \"%s is not a class/module\",
@@ -884,7 +1165,7 @@ module FastRuby
884
1165
  }
885
1166
  }
886
1167
  else {
887
- return rb_funcall(klass, #{tree[2].to_i}, 0, 0);
1168
+ return rb_funcall(klass, #{intern_num tree[2]}, 0, 0);
888
1169
  }
889
1170
 
890
1171
  return Qnil;
@@ -898,7 +1179,7 @@ module FastRuby
898
1179
 
899
1180
  verify_type_function = proc { |name| "
900
1181
  static VALUE #{name}(VALUE arg) {
901
- if (CLASS_OF(arg)!=#{klass.internal_value}) rb_raise(#{TypeMismatchAssignmentException.internal_value}, \"Illegal assignment at runtime (type mismatch)\");
1182
+ if (CLASS_OF(arg)!=#{literal_value klass}) rb_raise(#{literal_value FastRuby::TypeMismatchAssignmentException}, \"Illegal assignment at runtime (type mismatch)\");
902
1183
  return arg;
903
1184
  }
904
1185
  "
@@ -1010,7 +1291,7 @@ module FastRuby
1010
1291
 
1011
1292
  return inline_block("
1012
1293
  pframe->target_frame = (void*)-1;
1013
- pframe->exception = rb_funcall(#{to_c args[1]}, #{:exception.to_i},0);
1294
+ pframe->exception = rb_funcall(#{to_c args[1]}, #{intern_num :exception},0);
1014
1295
  longjmp(pframe->jmp, 1);
1015
1296
  return Qnil;
1016
1297
  ")
@@ -1047,144 +1328,164 @@ module FastRuby
1047
1328
  end
1048
1329
  end
1049
1330
 
1050
- convention = nil
1051
-
1052
- if recvtype.respond_to? :fastruby_method and inference_complete
1053
-
1054
- method_tree = nil
1055
- begin
1056
- method_tree = recvtype.instance_method(tree[2]).fastruby.tree
1057
- rescue NoMethodError
1058
- end
1331
+ if repass_var
1332
+ extraargs = ","+repass_var
1333
+ extraargs_signature = ",VALUE " + repass_var
1334
+ else
1335
+ extraargs = ""
1336
+ extraargs_signature = ""
1337
+ end
1059
1338
 
1060
- if method_tree
1061
- mobject = recvtype.build(signature, tree[2])
1062
- convention = :fastruby
1339
+ if argnum == 0
1340
+ value_cast = "VALUE,VALUE,VALUE"
1341
+ "((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(#{to_c recv}, Qfalse, (VALUE)pframe)"
1063
1342
  else
1064
- mobject = recvtype.instance_method(tree[2])
1065
- convention = :cruby
1343
+ value_cast = ( ["VALUE"]*(args.size) ).join(",") + ",VALUE,VALUE"
1344
+ "((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(#{to_c recv}, Qfalse, (VALUE)pframe, #{strargs})"
1066
1345
  end
1346
+
1347
+ else # else recvtype
1348
+ if argnum == 0
1349
+ protected_block("rb_funcall(#{to_c recv}, #{intern_num tree[2]}, 0)", false, repass_var)
1067
1350
  else
1068
- mobject = recvtype.instance_method(tree[2])
1069
- convention = :cruby
1351
+ protected_block("rb_funcall(#{to_c recv}, #{intern_num tree[2]}, #{argnum}, #{strargs} )", false, repass_var)
1070
1352
  end
1353
+ end # if recvtype
1354
+ end
1071
1355
 
1072
- address = nil
1073
- len = 0
1074
- if mobject
1075
- address = getaddress(mobject)
1076
- len = getlen(mobject)
1356
+ def get_class_name(argument)
1357
+ if argument.instance_of? Symbol
1358
+ argument.to_s
1359
+ elsif argument.instance_of? FastRuby::FastRubySexp
1360
+ if argument[0] == :colon3
1361
+ get_class_name(argument[1])
1362
+ elsif argument[0] == :colon2
1363
+ get_class_name(argument[2])
1077
1364
  end
1365
+ end
1366
+ end
1078
1367
 
1079
- if repass_var
1080
- extraargs = ","+repass_var
1081
- extraargs_signature = ",VALUE " + repass_var
1082
- else
1083
- extraargs = ""
1084
- extraargs_signature = ""
1368
+ def get_container_tree(argument)
1369
+ if argument.instance_of? Symbol
1370
+ s(:self)
1371
+ elsif argument.instance_of? FastRuby::FastRubySexp
1372
+ if argument[0] == :colon3
1373
+ s(:const, :Object)
1374
+ elsif argument[0] == :colon2
1375
+ argument[1]
1085
1376
  end
1377
+ end
1378
+ end
1086
1379
 
1087
- if address then
1088
- if argnum == 0
1089
- value_cast = "VALUE"
1090
- value_cast = value_cast + ", VALUE,VALUE" if convention == :fastruby
1380
+ def locals_scope(locals)
1381
+ old_locals = @locals
1382
+ old_locals_struct = @locals_struct
1091
1383
 
1092
- if convention == :fastruby
1093
- "((VALUE(*)(#{value_cast}))0x#{address.to_s(16)})(#{to_c recv}, Qfalse, (VALUE)pframe)"
1094
- else
1384
+ @locals = locals
1385
+ @locals_struct = "struct {
1386
+ void* block_function_address;
1387
+ VALUE block_function_param;
1388
+ jmp_buf jmp;
1389
+ VALUE return_value;
1390
+ void* pframe;
1391
+ #{@locals.map{|l| "VALUE #{l};\n"}.join}
1392
+ }"
1095
1393
 
1096
- str_incall_args = nil
1097
- if len == -1
1098
- str_incall_args = "0, (VALUE[]){}, recv"
1099
- value_cast = "int,VALUE*,VALUE"
1100
- elsif len == -2
1101
- str_incall_args = "recv, rb_ary_new4(#{})"
1102
- value_cast = "VALUE,VALUE"
1103
- else
1104
- str_incall_args = "recv"
1105
- end
1394
+ begin
1395
+ yield
1396
+ ensure
1397
+ @locals = old_locals
1398
+ @locals_struct = old_locals_struct
1399
+ end
1400
+ end
1106
1401
 
1107
- protected_block(
1108
-
1109
- anonymous_function{ |name| "
1110
- static VALUE #{name}(VALUE recv#{extraargs_signature}) {
1111
- // call to #{recvtype}##{mname}
1112
- if (rb_block_given_p()) {
1113
- // no passing block, recall
1114
- return rb_funcall(recv, #{tree[2].to_i}, 0);
1115
- } else {
1116
- return ((VALUE(*)(#{value_cast}))0x#{address.to_s(16)})(#{str_incall_args});
1117
- }
1118
- }
1119
- " } + "(#{to_c(recv)}#{extraargs})", false, repass_var)
1120
- end
1121
- else
1122
- value_cast = ( ["VALUE"]*(args.size) ).join(",")
1123
- value_cast = value_cast + ", VALUE, VALUE" if convention == :fastruby
1402
+ def method_group(init_code, tree)
1124
1403
 
1125
- wrapper_func = nil
1126
- if convention == :fastruby
1127
- "((VALUE(*)(#{value_cast}))0x#{address.to_s(16)})(#{to_c recv}, Qfalse, (VALUE)pframe, #{strargs})"
1128
- else
1404
+ alt_locals = Set.new
1405
+ alt_locals << :self
1129
1406
 
1130
- str_incall_args = nil
1131
- if len == -1
1132
- str_incall_args = "#{argnum}, (VALUE[]){#{ (1..argnum).map{|x| "_arg"+x.to_s }.join(",")}}, recv"
1133
- value_cast = "int,VALUE*,VALUE"
1134
- elsif len == -2
1135
- str_incall_args = "recv, rb_ary_new4(#{ (1..argnum).map{|x| "_arg"+x.to_s }.join(",")})"
1136
- value_cast = "VALUE,VALUE"
1137
- else
1138
- str_incall_args = "recv, #{ (1..argnum).map{|x| "_arg"+x.to_s }.join(",")}"
1139
- end
1407
+ FastRuby::GetLocalsProcessor.get_locals(tree).each do |local|
1408
+ alt_locals << local
1409
+ end
1140
1410
 
1141
- protected_block(
1142
-
1143
- anonymous_function{ |name| "
1144
- static VALUE #{name}(VALUE recv, #{ (1..argnum).map{|x| "VALUE _arg"+x.to_s }.join(",")} ) {
1145
- // call to #{recvtype}##{mname}
1146
- if (rb_block_given_p()) {
1147
- // no passing block, recall
1148
- return rb_funcall(recv, #{tree[2].to_i}, #{argnum}, #{ (1..argnum).map{|x| "_arg"+x.to_s }.join(",")});
1149
- } else {
1150
- return ((VALUE(*)(#{value_cast}))0x#{address.to_s(16)})(#{str_incall_args});
1151
- }
1152
- }
1153
- " } + "(#{to_c(recv)}, #{strargs})", false, repass_var
1154
- )
1155
- end
1156
- end
1157
- else
1411
+ fun = nil
1158
1412
 
1159
- if argnum == 0
1160
- protected_block("rb_funcall(#{to_c recv}, #{tree[2].to_i}, 0)", false, repass_var)
1161
- else
1162
- protected_block("rb_funcall(#{to_c recv}, #{tree[2].to_i}, #{argnum}, #{strargs} )", false, repass_var)
1163
- end
1164
- end
1413
+ locals_scope(alt_locals) do
1414
+ fun = anonymous_function { |method_name| "static VALUE #{method_name}(VALUE self) {
1165
1415
 
1166
- else
1167
- if argnum == 0
1168
- protected_block("rb_funcall(#{to_c recv}, #{tree[2].to_i}, 0)", false, repass_var)
1169
- else
1170
- protected_block("rb_funcall(#{to_c recv}, #{tree[2].to_i}, #{argnum}, #{strargs} )", false, repass_var)
1171
- end
1416
+ #{@frame_struct} frame;
1417
+ #{@locals_struct} locals;
1418
+ typeof(&frame) pframe = &frame;
1419
+ typeof(&locals) plocals = &locals;
1420
+
1421
+ frame.plocals = plocals;
1422
+ frame.parent_frame = 0;
1423
+ frame.return_value = Qnil;
1424
+ frame.target_frame = &frame;
1425
+ frame.exception = Qnil;
1426
+ frame.rescue = 0;
1427
+
1428
+ locals.self = self;
1429
+
1430
+ #{to_c tree};
1431
+ return Qnil;
1432
+ }
1433
+ "
1434
+ }
1172
1435
  end
1173
- end
1174
1436
 
1175
- def to_c_class(tree)
1176
1437
  inline_block("
1177
- rb_funcall(plocals->self,#{:fastruby.to_i},1,(VALUE)#{tree.internal_value});
1438
+ #{init_code}
1439
+
1440
+ rb_funcall(tmpklass, #{intern_num :__id__},0);
1441
+
1442
+ #{fun}(tmpklass);
1178
1443
  return Qnil;
1444
+
1445
+
1179
1446
  ")
1180
1447
 
1181
1448
  end
1182
1449
 
1450
+
1451
+
1452
+ def to_c_class(tree)
1453
+ str_class_name = get_class_name(tree[1])
1454
+ container_tree = get_container_tree(tree[1])
1455
+
1456
+ if container_tree == s(:self)
1457
+ method_group("
1458
+ VALUE tmpklass = rb_define_class(
1459
+ #{str_class_name.inspect},
1460
+ #{tree[2] ? to_c(tree[2]) : "rb_cObject"}
1461
+ );
1462
+ ", tree[3])
1463
+ else
1464
+ method_group("
1465
+ VALUE container_klass = #{to_c(container_tree)};
1466
+ VALUE tmpklass = rb_define_class_under(
1467
+ container_klass,
1468
+ #{str_class_name.inspect},
1469
+ #{tree[2] ? to_c(tree[2]) : "rb_cObject"}
1470
+ );
1471
+ ", tree[3])
1472
+ end
1473
+ end
1474
+
1183
1475
  def to_c_module(tree)
1184
- inline_block("
1185
- rb_funcall(plocals->self,#{:fastruby.to_i},1,(VALUE)#{tree.internal_value});
1186
- return Qnil;
1187
- ")
1476
+ str_class_name = get_class_name(tree[1])
1477
+ container_tree = get_container_tree(tree[1])
1478
+
1479
+ if container_tree == s(:self)
1480
+ method_group("
1481
+ VALUE tmpklass = rb_define_module(#{str_class_name.inspect});
1482
+ ", tree[2])
1483
+ else
1484
+ method_group("
1485
+ VALUE container_klass = #{to_c(container_tree)};
1486
+ VALUE tmpklass = rb_define_module_under(container_klass,#{str_class_name.inspect});
1487
+ ", tree[2])
1488
+ end
1188
1489
  end
1189
1490
 
1190
1491
  def to_c_while(tree)
@@ -1271,7 +1572,7 @@ module FastRuby
1271
1572
  def inline_block_reference(arg)
1272
1573
  code = nil
1273
1574
 
1274
- if arg.instance_of? Sexp
1575
+ if arg.instance_of? FastRuby::FastRubySexp
1275
1576
  code = to_c(arg);
1276
1577
  else
1277
1578
  code = arg
@@ -1292,7 +1593,7 @@ module FastRuby
1292
1593
 
1293
1594
  def inline_block(code, repass_var = nil)
1294
1595
  anonymous_function{ |name| "
1295
- static VALUE #{name}(VALUE param#{repass_var ? ",VALUE " + repass_var : "" }) {
1596
+ static VALUE #{name}(VALUE param#{repass_var ? ",void* " + repass_var : "" }) {
1296
1597
  #{@frame_struct} *pframe = (void*)param;
1297
1598
  #{@locals_struct} *plocals = (void*)pframe->plocals;
1298
1599
  VALUE last_expression = Qnil;
@@ -1304,7 +1605,7 @@ module FastRuby
1304
1605
  end
1305
1606
 
1306
1607
  def inline_ruby(proced, parameter)
1307
- "rb_funcall(#{proced.internal_value}, #{:call.to_i}, 1, #{parameter})"
1608
+ "rb_funcall(#{proced.__id__}, #{intern_num :call}, 1, #{parameter})"
1308
1609
  end
1309
1610
 
1310
1611
  def wrapped_break_block(inner_code)
@@ -1318,12 +1619,12 @@ module FastRuby
1318
1619
  def protected_block(inner_code, always_rescue = false,repass_var = nil)
1319
1620
  wrapper_code = "
1320
1621
  if (pframe->last_error != Qnil) {
1321
- if (CLASS_OF(pframe->last_error)==(VALUE)#{UnwindFastrubyFrame.internal_value}) {
1622
+ if (CLASS_OF(pframe->last_error)==#{literal_value FastRuby::Context::UnwindFastrubyFrame}) {
1322
1623
  #{@frame_struct} *pframe = (void*)param;
1323
1624
 
1324
- pframe->target_frame = (void*)FIX2LONG(rb_ivar_get(pframe->last_error, #{:@target_frame.to_i}));
1325
- pframe->exception = rb_ivar_get(pframe->last_error, #{:@ex.to_i});
1326
- pframe->return_value = rb_ivar_get(pframe->last_error, #{:@return_value.to_i});
1625
+ pframe->target_frame = (void*)FIX2LONG(rb_ivar_get(pframe->last_error, #{intern_num :@target_frame}));
1626
+ pframe->exception = rb_ivar_get(pframe->last_error, #{intern_num :@ex});
1627
+ pframe->return_value = rb_ivar_get(pframe->last_error, #{intern_num :@return_value});
1327
1628
 
1328
1629
  if (pframe->target_frame == (void*)-2) {
1329
1630
  return pframe->return_value;
@@ -1360,7 +1661,7 @@ module FastRuby
1360
1661
  }
1361
1662
 
1362
1663
  rescue_args = ""
1363
- rescue_args = "(VALUE)(VALUE[]){(VALUE)pframe,#{repass_var}}"
1664
+ rescue_args = "(VALUE)(VALUE[]){(VALUE)pframe,(VALUE)#{repass_var}}"
1364
1665
  else
1365
1666
  body = inline_block_reference("return #{inner_code}")
1366
1667
  rescue_args = "(VALUE)pframe"
@@ -1446,6 +1747,216 @@ module FastRuby
1446
1747
  "
1447
1748
  end
1448
1749
 
1750
+ def c_escape(str)
1751
+ str.inspect
1752
+ end
1753
+
1754
+ def literal_value(value)
1755
+ @literal_value_hash = Hash.new unless @literal_value_hash
1756
+ return @literal_value_hash[value] if @literal_value_hash[value]
1757
+
1758
+ name = self.add_global_name("VALUE", "Qnil");
1759
+
1760
+ begin
1761
+ str = Marshal.dump(value)
1762
+
1763
+ init_extra << "
1764
+ #{name} = rb_marshal_load(rb_str_new(#{c_escape str}, #{str.size}));
1765
+ rb_funcall(#{name},#{intern_num :gc_register_object},0);
1766
+
1767
+ "
1768
+ rescue TypeError
1769
+ @no_cache = true
1770
+ FastRuby.logger.info "#{value} disabling cache for extension"
1771
+ init_extra << "
1772
+ #{name} = rb_funcall(rb_const_get(rb_cObject, #{intern_num :ObjectSpace}), #{intern_num :_id2ref}, 1, INT2FIX(#{value.__id__}));
1773
+ "
1774
+
1775
+ end
1776
+ @literal_value_hash[value] = name
1777
+
1778
+ name
1779
+ end
1780
+
1781
+ def encode_address(recvtype,signature,mname,call_tree,inference_complete,convention_global_name = nil)
1782
+ name = self.add_global_name("void*", 0);
1783
+ cruby_name = self.add_global_name("void*", 0);
1784
+ cruby_len = self.add_global_name("int", 0);
1785
+ args_tree = call_tree[3]
1786
+ method_tree = nil
1787
+
1788
+ begin
1789
+ method_tree = recvtype.instance_method(@method_name.to_sym).fastruby.tree
1790
+ rescue NoMethodError
1791
+ end
1792
+
1793
+
1794
+ strargs_signature = (0..args_tree.size-2).map{|x| "VALUE arg#{x}"}.join(",")
1795
+ strargs = (0..args_tree.size-2).map{|x| "arg#{x}"}.join(",")
1796
+ inprocstrargs = (1..args_tree.size-1).map{|x| "((VALUE*)method_arguments)[#{x}]"}.join(",")
1797
+
1798
+ if args_tree.size > 1
1799
+ strargs_signature = "," + strargs_signature
1800
+ toprocstrargs = "self,"+strargs
1801
+ strargs = "," + strargs
1802
+ inprocstrargs = ","+inprocstrargs
1803
+ else
1804
+ toprocstrargs = "self"
1805
+ end
1806
+
1807
+ ruby_wrapper = anonymous_function{ |funcname| "
1808
+ static VALUE #{funcname}(VALUE self,void* block,void* frame#{strargs_signature}){
1809
+ #{@frame_struct}* pframe = frame;
1810
+
1811
+ VALUE method_arguments[#{args_tree.size}] = {#{toprocstrargs}};
1812
+
1813
+ return #{
1814
+ protected_block "rb_funcall(((VALUE*)method_arguments)[0], #{intern_num mname.to_sym}, #{args_tree.size-1}#{inprocstrargs});", false, "method_arguments"
1815
+ };
1816
+ }
1817
+ "
1818
+ }
1819
+
1820
+ value_cast = ( ["VALUE"]*(args_tree.size) ).join(",")
1821
+
1822
+ cruby_wrapper = anonymous_function{ |funcname| "
1823
+ static VALUE #{funcname}(VALUE self,void* block,void* frame#{strargs_signature}){
1824
+ #{@frame_struct}* pframe = frame;
1825
+
1826
+ VALUE method_arguments[#{args_tree.size}] = {#{toprocstrargs}};
1827
+
1828
+ // call to #{recvtype}::#{mname}
1829
+
1830
+ if (#{cruby_len} == -1) {
1831
+ return #{
1832
+ protected_block "((VALUE(*)(int,VALUE*,VALUE))#{cruby_name})(#{args_tree.size-1}, ((VALUE*)method_arguments)+1,*((VALUE*)method_arguments));", false, "method_arguments"
1833
+ };
1834
+
1835
+ } else if (#{cruby_len} == -2) {
1836
+ return #{
1837
+ protected_block "((VALUE(*)(VALUE,VALUE))#{cruby_name})(*((VALUE*)method_arguments), rb_ary_new4(#{args_tree.size-1},((VALUE*)method_arguments)+1) );", false, "method_arguments"
1838
+ };
1839
+
1840
+ } else {
1841
+ return #{
1842
+ protected_block "((VALUE(*)(#{value_cast}))#{cruby_name})(((VALUE*)method_arguments)[0] #{inprocstrargs});", false, "method_arguments"
1843
+ };
1844
+ }
1845
+ }
1846
+ "
1847
+ }
1848
+
1849
+ recvdump = nil
1850
+
1851
+ begin
1852
+ recvdump = literal_value recvtype
1853
+ rescue
1854
+ end
1855
+
1856
+ if recvdump and recvtype
1857
+ init_extra << "
1858
+ {
1859
+ VALUE recvtype = #{recvdump};
1860
+ rb_funcall(#{literal_value FastRuby}, #{intern_num :set_builder_module}, 1, recvtype);
1861
+ VALUE signature = #{literal_value signature};
1862
+ VALUE mname = #{literal_value mname};
1863
+ VALUE tree = #{literal_value method_tree};
1864
+ VALUE convention = rb_funcall(recvtype, #{intern_num :convention}, 3,signature,mname,#{inference_complete ? "Qtrue" : "Qfalse"});
1865
+ VALUE mobject = rb_funcall(recvtype, #{intern_num :method_from_signature},3,signature,mname,#{inference_complete ? "Qtrue" : "Qfalse"});
1866
+
1867
+ struct METHOD {
1868
+ VALUE klass, rklass;
1869
+ VALUE recv;
1870
+ ID id, oid;
1871
+ int safe_level;
1872
+ NODE *body;
1873
+ };
1874
+
1875
+ int len = 0;
1876
+ void* address = 0;
1877
+
1878
+ if (mobject != Qnil) {
1879
+
1880
+ struct METHOD *data;
1881
+ Data_Get_Struct(mobject, struct METHOD, data);
1882
+
1883
+ if (nd_type(data->body) == NODE_CFUNC) {
1884
+ address = data->body->nd_cfnc;
1885
+ len = data->body->nd_argc;
1886
+ }
1887
+ }
1888
+
1889
+ #{convention_global_name ? convention_global_name + " = 0;" : ""}
1890
+ if (recvtype != Qnil) {
1891
+
1892
+ if (convention == #{literal_value :fastruby}) {
1893
+ #{convention_global_name ? convention_global_name + " = 1;" : ""}
1894
+ #{name} = address;
1895
+ } else if (convention == #{literal_value :cruby}) {
1896
+ // cruby, wrap direct call
1897
+ #{cruby_name} = address;
1898
+
1899
+ if (#{cruby_name} == 0) {
1900
+ #{name} = (void*)#{ruby_wrapper};
1901
+ } else {
1902
+ #{cruby_len} = len;
1903
+ #{name} = (void*)#{cruby_wrapper};
1904
+ }
1905
+ } else {
1906
+ // ruby, wrap rb_funcall
1907
+ #{name} = (void*)#{ruby_wrapper};
1908
+ }
1909
+ } else {
1910
+ // ruby, wrap rb_funcall
1911
+ #{name} = (void*)#{ruby_wrapper};
1912
+ }
1913
+
1914
+ }
1915
+ "
1916
+ else
1917
+ init_extra << "
1918
+ // ruby, wrap rb_funcall
1919
+ #{name} = (void*)#{ruby_wrapper};
1920
+ "
1921
+ end
1922
+
1923
+ name
1924
+ end
1925
+
1926
+ def intern_num(symbol)
1927
+ @intern_num_hash = Hash.new unless @intern_num_hash
1928
+ return @intern_num_hash[symbol] if @intern_num_hash[symbol]
1929
+
1930
+ name = self.add_global_name("ID", 0);
1931
+
1932
+ init_extra << "
1933
+ #{name} = rb_intern(\"#{symbol.to_s}\");
1934
+ "
1935
+
1936
+ @intern_num_hash[symbol] = name
1937
+
1938
+ name
1939
+ end
1940
+
1941
+ def add_global_name(ctype, default)
1942
+ name = "glb" + rand(1000000000).to_s
1943
+
1944
+ extra_code << "
1945
+ static #{ctype} #{name} = #{default};
1946
+ "
1947
+ name
1948
+ end
1949
+
1950
+ def global_entry(glbname)
1951
+ name = add_global_name("struct global_entry*", 0);
1952
+
1953
+ init_extra << "
1954
+ #{name} = rb_global_entry(SYM2ID(#{literal_value glbname}));
1955
+ "
1956
+
1957
+ name
1958
+ end
1959
+
1449
1960
 
1450
1961
  def frame(code, jmp_code, not_jmp_code = "", rescued = nil)
1451
1962
 
@@ -1498,55 +2009,5 @@ module FastRuby
1498
2009
  "
1499
2010
  } + "((VALUE)pframe)"
1500
2011
  end
1501
-
1502
- inline :C do |builder|
1503
- builder.include "<node.h>"
1504
- builder.c "VALUE getaddress(VALUE method) {
1505
- struct METHOD {
1506
- VALUE klass, rklass;
1507
- VALUE recv;
1508
- ID id, oid;
1509
- int safe_level;
1510
- NODE *body;
1511
- };
1512
-
1513
- struct METHOD *data;
1514
- Data_Get_Struct(method, struct METHOD, data);
1515
-
1516
- if (nd_type(data->body) == NODE_CFUNC) {
1517
- return INT2FIX(data->body->nd_cfnc);
1518
- }
1519
-
1520
- return Qnil;
1521
- }"
1522
-
1523
- builder.c "VALUE getlen(VALUE method) {
1524
- struct METHOD {
1525
- VALUE klass, rklass;
1526
- VALUE recv;
1527
- ID id, oid;
1528
- int safe_level;
1529
- NODE *body;
1530
- };
1531
-
1532
- struct METHOD *data;
1533
- Data_Get_Struct(method, struct METHOD, data);
1534
-
1535
- if (nd_type(data->body) == NODE_CFUNC) {
1536
- return INT2FIX(data->body->nd_argc);
1537
- }
1538
-
1539
- return Qnil;
1540
- }"
1541
-
1542
- builder.c "VALUE global_entry(VALUE global_id) {
1543
- ID id = SYM2ID(global_id);
1544
- struct global_entry* entry;
1545
-
1546
- entry = rb_global_entry(id);
1547
- return INT2FIX(entry);
1548
- }
1549
- "
1550
- end
1551
2012
  end
1552
2013
  end