fastruby 0.0.13 → 0.0.14

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ 0.0.14 Support for method replacement ("monkey patching")
2
+
3
+ Internal: Implemented method hash to store implementation pointers
4
+
5
+ Internal: Fixed inference of arguments on methods with splat arguments
6
+
1
7
  0.0.13 Argument splat method calls (not optimized yet)
2
8
 
3
9
  Array arguments on methods (optional arguments, variable number of arguments)
data/README CHANGED
@@ -57,10 +57,11 @@ I will stabilize the API and document it for next releases. I promise
57
57
 
58
58
  == Known Limitations & Issues
59
59
 
60
- * monkey patching does not work with fastruby methods
61
60
  * callcc is not supported, it works but using it may result in unexpected behaviour
62
61
  * recursive methods will be slow since the optimization of method calls only works with already defined methods
63
- * calls with blocks to ruby or cruby methods are almost as slow as normal ruby (if the called method is defined by fastruby, the call it's pretty fast)
62
+ * calls with blocks to ruby or cruby methods are almost as slow as normal ruby (if the called method is defined by fastruby, the call is pretty fast)
63
+ * When calling fastruby methods from normal ruby, the max. number of arguments allowed is 15
64
+ * replacement of methods using identical code strings will work, but it will generate duplicated objects on the cache each time te snippet run
64
65
 
65
66
  == Usage
66
67
 
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ require "rspec/core/rake_task"
7
7
 
8
8
  spec = Gem::Specification.new do |s|
9
9
  s.name = 'fastruby'
10
- s.version = '0.0.13'
10
+ s.version = '0.0.14'
11
11
  s.author = 'Dario Seminara'
12
12
  s.email = 'robertodarioseminara@gmail.com'
13
13
  s.platform = Gem::Platform::RUBY
@@ -0,0 +1,77 @@
1
+ require "rubygems"
2
+ require "fastruby"
3
+
4
+ class X
5
+ fastruby "
6
+ def factorial(n)
7
+ if n > 1
8
+ n * factorial((n-1).infer(Fixnum))
9
+ else
10
+ 1
11
+ end
12
+ end
13
+ "
14
+ end
15
+
16
+ class Y
17
+ fastruby "
18
+ def bar(x)
19
+ i = 100000
20
+
21
+ lvar_type(i,Fixnum)
22
+
23
+ ret = 0
24
+ while i > 0
25
+ x.factorial(20)
26
+ i = i - 1
27
+ end
28
+ return ret
29
+ end
30
+
31
+ "
32
+ end
33
+
34
+ class X2
35
+ def factorial(n)
36
+ if n > 1
37
+ n * factorial(n-1)
38
+ else
39
+ 1
40
+ end
41
+ end
42
+ end
43
+
44
+ class Y2
45
+ def bar(x)
46
+ i = 100000
47
+
48
+ ret = 0
49
+ while i > 0
50
+ x.factorial(20)
51
+ i = i - 1
52
+ end
53
+ return ret
54
+ end
55
+
56
+ end
57
+
58
+
59
+ x = X.new
60
+ y = Y.new
61
+ y2 = Y2.new
62
+ x2 = X2.new
63
+
64
+ Y.build([Y,X],:bar)
65
+
66
+ require 'benchmark'
67
+
68
+ Benchmark::bm(20) do |b|
69
+
70
+ b.report("fastruby") do
71
+ y.bar(x)
72
+ end
73
+
74
+ b.report("ruby") do
75
+ y2.bar(x2)
76
+ end
77
+ end
@@ -1,5 +1,7 @@
1
1
  #include "fastruby_base.inl"
2
2
 
3
3
  void Init_fastruby_base() {
4
- Init_stack_chunk();
4
+ init_stack_chunk();
5
+ init_class_extension();
6
+ init_fastruby_method();
5
7
  }
@@ -25,6 +25,13 @@ struct FASTRUBYTHREADDATA {
25
25
  VALUE rb_stack_chunk;
26
26
  };
27
27
 
28
+ struct METHOD {
29
+ VALUE klass, rklass;
30
+ VALUE recv;
31
+ ID id, oid;
32
+ int safe_level;
33
+ NODE *body;
34
+ };
28
35
 
29
36
  static inline void stack_chunk_initialize(struct STACKCHUNK* sc) {
30
37
  // initialize pointers with zeros
@@ -207,7 +214,7 @@ static inline struct FASTRUBYTHREADDATA* rb_current_thread_data() {
207
214
  Data_Get_Struct(rb_thread_data,struct FASTRUBYTHREADDATA,thread_data);
208
215
  return thread_data;
209
216
  }
210
-
217
+
211
218
  static void init_stack_chunk() {
212
219
 
213
220
  rb_mFastRuby = rb_define_module("FastRuby");
@@ -220,3 +227,74 @@ static void init_stack_chunk() {
220
227
  rb_define_method(rb_cStackChunk, "alloc", rb_stack_chunk_alloc,1);
221
228
  }
222
229
 
230
+ static VALUE clear_method_hash_addresses(VALUE klass,VALUE rb_method_hash) {
231
+
232
+ if (rb_method_hash != Qnil) {
233
+ VALUE rb_values = rb_funcall(rb_method_hash, rb_intern("values"),0);
234
+ void** address;
235
+ int i;
236
+
237
+ for (i = 0; i < RARRAY(rb_values)->len; i++) {
238
+ address = (void**)FIX2LONG(rb_ary_entry(rb_values,i));
239
+ *address = 0;
240
+ }
241
+ }
242
+
243
+ return Qnil;
244
+ }
245
+
246
+ static VALUE has_fastruby_function(VALUE self, VALUE rb_method_hash, VALUE mname) {
247
+ ID id = rb_intern(RSTRING(mname)->ptr);
248
+ VALUE tmp = rb_hash_aref(rb_method_hash, LONG2FIX(id));
249
+
250
+ if (tmp != Qnil) {
251
+ void** address = (void**)FIX2LONG(tmp);
252
+
253
+ if (*address == 0) {
254
+ return Qfalse;
255
+ } else {
256
+ return Qtrue;
257
+ }
258
+ }
259
+
260
+ return Qfalse;
261
+ }
262
+
263
+ static void init_class_extension() {
264
+ VALUE rb_mFastRubyBuilderModule = rb_define_module_under(rb_mFastRuby, "BuilderModule");
265
+ rb_define_method(rb_mFastRubyBuilderModule, "clear_method_hash_addresses",clear_method_hash_addresses,1);
266
+ rb_define_method(rb_mFastRubyBuilderModule, "has_fastruby_function",has_fastruby_function,2);
267
+ }
268
+
269
+ static VALUE fastruby_method_tree(VALUE self) {
270
+ VALUE rb_tree_pointer = rb_ivar_get(self, rb_intern("@tree"));
271
+ if (rb_tree_pointer == Qnil) return Qnil;
272
+ VALUE* tree_pointer = (VALUE*)FIX2LONG(rb_tree_pointer);
273
+ return *tree_pointer;
274
+ }
275
+
276
+ static VALUE fastruby_method_tree_pointer(VALUE self) {
277
+ VALUE rb_tree_pointer = rb_ivar_get(self, rb_intern("@tree"));
278
+
279
+ if (rb_tree_pointer == Qnil) {
280
+ VALUE* tree_pointer = malloc(sizeof(VALUE*));
281
+ *tree_pointer = Qnil;
282
+ rb_tree_pointer = LONG2FIX(tree_pointer);
283
+ rb_ivar_set(self, rb_intern("@tree"), rb_tree_pointer);
284
+ }
285
+
286
+ return rb_tree_pointer;
287
+ }
288
+
289
+ static VALUE fastruby_method_tree_eq(VALUE self, VALUE val) {
290
+ VALUE* tree_pointer = (VALUE*)FIX2LONG(fastruby_method_tree_pointer(self));
291
+ *tree_pointer = val;
292
+ return Qnil;
293
+ }
294
+
295
+ static void init_fastruby_method() {
296
+ VALUE rb_cFastRubyMethod = rb_define_class_under(rb_mFastRuby, "Method", rb_cObject);
297
+ rb_define_method(rb_cFastRubyMethod, "tree_pointer", fastruby_method_tree_pointer,0);
298
+ rb_define_method(rb_cFastRubyMethod, "tree", fastruby_method_tree,0);
299
+ rb_define_method(rb_cFastRubyMethod, "tree=", fastruby_method_tree_eq,1);
300
+ }
@@ -22,6 +22,9 @@ require "fastruby/inline_extension"
22
22
  require "fastruby/method_extension"
23
23
  require "fastruby/logging"
24
24
  require "fastruby/getlocals"
25
+ require "fastruby_load_path"
26
+
27
+ require FastRuby.fastruby_load_path + "/../ext/fastruby_base/fastruby_base"
25
28
 
26
29
  module FastRuby
27
30
 
@@ -43,7 +46,6 @@ module FastRuby
43
46
  end
44
47
 
45
48
  class Method
46
- attr_accessor :tree
47
49
  attr_accessor :locals
48
50
  attr_accessor :options
49
51
  attr_accessor :snippet_hash
@@ -53,75 +55,28 @@ module FastRuby
53
55
  @owner = owner
54
56
  end
55
57
 
56
- def method_from_signature(signature, inference_complete)
57
- begin
58
- recvtype = @owner
59
- if recvtype.respond_to? :fastruby_method and inference_complete
58
+ def build(signature, noreturn = false)
59
+ return nil unless tree
60
+
61
+ no_cache = false
60
62
 
61
- method_tree = nil
62
- begin
63
- method_tree = recvtype.instance_method(@method_name.to_sym).fastruby.tree
64
- rescue NoMethodError
65
- end
63
+ mname = FastRuby.make_str_signature(@method_name, signature)
66
64
 
67
- if method_tree
68
- recvtype.build(signature, @method_name.to_sym)
69
- else
70
- recvtype.instance_method(@method_name.to_sym)
71
- end
72
- else
73
- recvtype.instance_method(@method_name.to_sym)
65
+ if @owner.respond_to? :method_hash
66
+ method_hash = @owner.method_hash(@method_name.to_sym) || {}
67
+ if (@owner.has_fastruby_function(method_hash,mname.to_s))
68
+ FastRuby.logger.info "NOT Building #{@owner}::#{@method_name} for signature #{signature.inspect}, it's already done"
69
+ return nil
74
70
  end
75
- rescue NameError
76
- nil
77
71
  end
78
- end
79
-
80
- def convention(signature, inference_complete)
81
- recvtype = @owner
82
- if recvtype.respond_to? :fastruby_method and inference_complete
83
72
 
84
- method_tree = nil
85
- begin
86
- method_tree = recvtype.instance_method(@method_name.to_sym).fastruby.tree
87
- rescue NoMethodError, NameError
88
- end
73
+ FastRuby.logger.info "Building #{@owner}::#{@method_name} for signature #{signature.inspect}"
89
74
 
90
- if method_tree
91
-
92
- args_tree = method_tree[2]
93
-
94
- if args_tree.any?{|x|x.to_s.match(/\*/)}
95
- :fastruby_array
96
- else
97
- :fastruby
98
- end
99
- else
100
- :cruby
101
- end
102
- else
103
- :cruby
104
- end
105
- end
106
-
107
- def build(signature, noreturn = false)
75
+
108
76
  require "fastruby/translator/translator"
109
77
  require "rubygems"
110
78
  require "inline"
111
79
 
112
- no_cache = false
113
-
114
- mname = FastRuby.make_str_signature(@method_name, signature)
115
-
116
- begin
117
- if (@owner.instance_method(mname))
118
- FastRuby.logger.info "NOT Building #{@owner}::#{@method_name} for signature #{signature.inspect}, it's already done"
119
- return @owner.instance_method(mname)
120
- end
121
- rescue NameError
122
- FastRuby.logger.info "Building #{@owner}::#{@method_name} for signature #{signature.inspect}"
123
- end
124
-
125
80
  context = FastRuby::Context.new
126
81
  context.locals = locals
127
82
  context.options = options
@@ -134,11 +89,17 @@ module FastRuby
134
89
 
135
90
  (1..signature.size).each do |i|
136
91
  arg = args_tree[i]
137
- context.infer_lvar_map[arg] = signature[i]
92
+ if arg
93
+ if arg.to_s.match(/\*/)
94
+ context.infer_lvar_map[arg.to_s.gsub("*","").to_sym] = Array
95
+ else
96
+ context.infer_lvar_map[arg.to_sym] = signature[i]
97
+ end
98
+ end
138
99
  end
139
100
 
140
101
  context.infer_self = signature[0]
141
- c_code = context.to_c_method(tree)
102
+ c_code = context.to_c_method(tree,signature)
142
103
 
143
104
  unless options[:main]
144
105
  context.define_method_at_init(@owner,@method_name, args_tree.size+1, signature)
@@ -213,16 +174,13 @@ module FastRuby
213
174
  FastRuby.cache.insert(snippet_hash, so_name) unless no_cache
214
175
  end
215
176
 
216
- if noreturn then
217
- nil
218
- else
219
- ret = @owner.instance_method(mname)
177
+ ret = Object.new
220
178
 
221
- ret.extend MethodExtent
222
- ret.yield_signature = context.yield_signature
179
+ ret.extend MethodExtent
180
+ ret.yield_signature = context.yield_signature
181
+
182
+ ret
223
183
 
224
- ret
225
- end
226
184
  end
227
185
 
228
186
  module MethodExtent
@@ -235,12 +193,22 @@ module FastRuby
235
193
  fastruby_method(method_name.to_sym).build(signature, noreturn)
236
194
  end
237
195
 
238
- def convention(signature, method_name, inference_complete)
239
- fastruby_method(method_name.to_sym).convention(signature, inference_complete)
196
+ def register_method_value(method_name,key,value)
197
+ @method_hash = Hash.new unless @method_hash
198
+ @method_hash[method_name] = Hash.new unless @method_hash[method_name]
199
+ @method_hash[method_name][key] = value
240
200
  end
241
-
242
- def method_from_signature(signature, method_name, inference_complete)
243
- fastruby_method(method_name.to_sym).method_from_signature(signature, inference_complete)
201
+
202
+ def method_hash(method_name)
203
+ @method_hash = Hash.new unless @method_hash
204
+ @method_hash[method_name]
205
+ end
206
+
207
+ def method_added(method_name)
208
+ if self.respond_to? :clear_method_hash_addresses
209
+ FastRuby.unset_tree(self,method_name)
210
+ self.clear_method_hash_addresses(method_hash(method_name))
211
+ end
244
212
  end
245
213
 
246
214
  def fastruby_method(mname_)
@@ -86,7 +86,7 @@ class Object
86
86
  else
87
87
 
88
88
  objs.sort{|x,y|
89
- (y =~ /Inline_Object/ ? 1 : 0) - (x =~ /Inline_Object/ ? 1 : 0)
89
+ File.new(x).ctime <=> File.new(y).ctime
90
90
  }.each do |obj|
91
91
 
92
92
  begin
@@ -35,6 +35,12 @@ module FastRuby
35
35
  end
36
36
  end
37
37
  end
38
+
39
+ def self.unset_tree(klass, method_name)
40
+ fastrubym = klass.fastruby_method(method_name)
41
+ fastrubym.tree = nil
42
+ nil
43
+ end
38
44
 
39
45
  def self.set_tree(klass, method_name, tree, snippet_hash, options = {})
40
46
  locals = Set.new
@@ -98,9 +98,8 @@ module FastRuby
98
98
 
99
99
  args[1..-1].each do |arg|
100
100
  argtype = infer_type(arg)
101
- if argtype
102
- signature << argtype
103
- else
101
+ signature << argtype
102
+ unless argtype
104
103
  inference_complete = false
105
104
  end
106
105
  end
@@ -32,45 +32,9 @@ module FastRuby
32
32
  hash = Hash.new
33
33
  value_cast = ( ["VALUE"]*(args_tree.size+2) ).join(",")
34
34
 
35
- multiple_arguments = args_tree[1..-1].find{|x| x.to_s =~ /\*/}
35
+ strmethodargs = "self,block,(VALUE)&frame"
36
36
 
37
- args_array_accessors = if multiple_arguments
38
- (0..args_tree.size-3).map{|x| "argv[#{x}]"} + ["argarray"]
39
- else
40
- (0..args_tree.size-2).map{|x| "argv[#{x}]"}
41
- end
42
-
43
- strmethodargs = ""
44
-
45
- if args_tree.size > 1
46
- strmethodargs = "self,block,(VALUE)&frame,#{args_array_accessors.map(&:to_s).join(",") }"
47
- else
48
- strmethodargs = "self,block,(VALUE)&frame"
49
- end
50
-
51
- strmakecall = if multiple_arguments
52
- "
53
- if (argc_ > #{args_tree.size-2}) {
54
- VALUE argarray = rb_ary_new4(argc_-#{args_tree.size-2}, argv+#{args_tree.size-2});
55
- return ((VALUE(*)(#{value_cast}))body->nd_cfnc)(#{strmethodargs});
56
- } else if (argc_ == #{args_tree.size-2}) {
57
- // pass pre-calculated method arguments plus an empty array
58
- VALUE argarray = rb_ary_new();
59
- return ((VALUE(*)(#{value_cast}))body->nd_cfnc)(#{strmethodargs});
60
- } else {
61
- rb_raise(rb_eArgError, \"wrong number of arguments (%d for #{args_tree.size-2}))\", argc_);
62
- }
63
- "
64
- else
65
- "if (argc_ == #{args_tree.size-1} && argc == #{args_tree.size+1}) {
66
- return ((VALUE(*)(#{value_cast}))body->nd_cfnc)(#{strmethodargs});
67
- } else {
68
- rb_raise(rb_eArgError, \"wrong number of arguments (%d for #{args_tree.size-1}))\", argc_);
69
- }"
70
- end
71
-
72
37
  anonymous_method_name = anonymous_function{ |anonymous_method_name| "VALUE #{anonymous_method_name}(int argc_, VALUE* argv, VALUE self) {
73
-
74
38
  VALUE klass = #{global_klass_variable};
75
39
  char method_name[0x100];
76
40
 
@@ -78,47 +42,58 @@ module FastRuby
78
42
  method_name[1] = 0;
79
43
 
80
44
  sprintf(method_name+1, \"#{method_name}\");
45
+ sprintf(method_name+strlen(method_name), \"%lu\", FIX2LONG(rb_obj_id(CLASS_OF(self))));
81
46
 
82
- int i;
83
- for (i=0; i<argc_; i++) {
84
- sprintf(method_name+strlen(method_name), \"%lu\", FIX2LONG(rb_obj_id(CLASS_OF(argv[i]))));
85
- }
47
+ int i;
48
+ for (i=0; i<argc_; i++) {
49
+ sprintf(method_name+strlen(method_name), \"%lu\", FIX2LONG(rb_obj_id(CLASS_OF(argv[i]))));
50
+ }
86
51
 
87
- NODE* body;
52
+ void** address = 0;
53
+ void* fptr = 0;
88
54
  ID id;
55
+ VALUE rb_method_hash;
89
56
 
90
57
  id = rb_intern(method_name);
91
- body = rb_method_node(klass,id);
58
+ rb_method_hash = rb_funcall(klass, #{intern_num :method_hash},1,#{literal_value method_name});
59
+
60
+ if (rb_method_hash != Qnil) {
61
+ VALUE tmp = rb_hash_aref(rb_method_hash, LONG2FIX(id));
62
+ if (tmp != Qnil) {
63
+ address = (void**)FIX2LONG(tmp);
64
+ fptr = *address;
65
+ }
66
+ }
92
67
 
93
- if (body == 0) {
94
- VALUE argv_class[argc_+1];
68
+ if (fptr == 0) {
69
+ VALUE argv_class[argc_+1];
70
+
71
+ argv_class[0] = CLASS_OF(self);
72
+ for (i=0; i<argc_; i++) {
73
+ argv_class[i+1] = CLASS_OF(argv[i]);
74
+ }
75
+
76
+ VALUE signature = rb_ary_new4(argc_+1,argv_class);
77
+
78
+ rb_funcall(#{global_klass_variable}, #{intern_num :build}, 2, signature,rb_str_new2(#{method_name.to_s.inspect}));
79
+
80
+ id = rb_intern(method_name);
81
+ rb_method_hash = rb_funcall(klass, #{intern_num :method_hash},1,#{literal_value method_name});
95
82
 
96
- argv_class[0] = CLASS_OF(self);
97
- for (i=0; i<argc_; i++) {
98
- argv_class[i+1] = CLASS_OF(argv[i]);
83
+ if (rb_method_hash != Qnil) {
84
+ VALUE tmp = rb_hash_aref(rb_method_hash, LONG2FIX(id));
85
+ if (tmp != Qnil) {
86
+ address = (void**)FIX2LONG(tmp);
87
+ fptr = *address;
88
+ }
99
89
  }
100
90
 
101
- VALUE signature = rb_ary_new4(argc_+1,argv_class);
102
- VALUE mobject = rb_funcall(#{global_klass_variable}, #{intern_num :build}, 2, signature,rb_str_new2(#{method_name.to_s.inspect}));
103
-
104
- struct METHOD {
105
- VALUE klass, rklass;
106
- VALUE recv;
107
- ID id, oid;
108
- int safe_level;
109
- NODE *body;
110
- };
111
-
112
- struct METHOD *data;
113
- Data_Get_Struct(mobject, struct METHOD, data);
114
- body = data->body;
115
-
116
- if (body == 0) {
117
- rb_raise(rb_eRuntimeError,\"method not found after build: '%s'\", method_name);
91
+ if (fptr == 0) {
92
+ rb_raise(rb_eRuntimeError, \"Error: method not found after build\");
118
93
  }
94
+
119
95
  }
120
96
 
121
- if (nd_type(body) == NODE_CFUNC) {
122
97
  struct {
123
98
  void* parent_frame;
124
99
  void* plocals;
@@ -137,8 +112,6 @@ module FastRuby
137
112
  frame.thread_data = rb_current_thread_data();
138
113
  frame.targetted = 0;
139
114
 
140
- int argc = body->nd_argc;
141
-
142
115
  VALUE block = Qfalse;
143
116
 
144
117
  if (rb_block_given_p()) {
@@ -166,10 +139,15 @@ module FastRuby
166
139
  return Qnil;
167
140
  }
168
141
 
169
- #{strmakecall}
170
- }
142
+ if (argc_ == 0) return ((VALUE(*)(VALUE,VALUE,VALUE))fptr)(#{strmethodargs});
143
+
144
+ #{ (1..15).map{ |i|
145
+ value_cast = ( ["VALUE"]*(i+3) ).join(",")
146
+ "if (argc_ == #{i}) return ((VALUE(*)(#{value_cast}))fptr)(#{strmethodargs}, #{(0..i-1).map{|x| "argv[#{x}]"}.join(",")});"
147
+ }.join("\n");
148
+ }
171
149
 
172
- return Qnil;
150
+ rb_raise(rb_eArgError, \"too many arguments: %d\", argc_);
173
151
  }"
174
152
  }
175
153
 
@@ -179,8 +157,9 @@ module FastRuby
179
157
  alt_options.delete(:main)
180
158
 
181
159
  inline_block "
160
+ rb_define_method(plocals->self, #{method_name.to_s.inspect}, #{anonymous_method_name}, -1 );
161
+
182
162
  #{global_klass_variable} = plocals->self;
183
-
184
163
  // set tree
185
164
  rb_funcall(#{literal_value FastRuby}, #{intern_num :set_tree}, 5,
186
165
  #{global_klass_variable},
@@ -191,7 +170,6 @@ module FastRuby
191
170
 
192
171
  );
193
172
 
194
- rb_define_method(plocals->self, #{method_name.to_s.inspect}, #{anonymous_method_name}, -1 );
195
173
  "
196
174
 
197
175
  end
@@ -463,10 +463,9 @@ module FastRuby
463
463
 
464
464
  call_frame_struct_code = "
465
465
  #{@block_struct} block;
466
- #{@locals_struct} *plocals = (void*)param;
467
466
 
468
467
  block.block_function_address = (void*)#{anonymous_function(&block_code)};
469
- block.block_function_param = (void*)param;
468
+ block.block_function_param = (void*)plocals;
470
469
 
471
470
  // create a call_frame
472
471
  #{@frame_struct} call_frame;
@@ -534,48 +533,45 @@ module FastRuby
534
533
  };
535
534
  "
536
535
 
537
- if call_args_tree.size > 1 ? call_args_tree.last[0] == :splat : false
536
+ recvtype = nil if call_args_tree.size > 1 ? call_args_tree.last[0] == :splat : false
537
+ unless recvtype
538
538
  inline_block "
539
539
  #{funcall_call_code}
540
540
  "
541
541
  else
542
+ encoded_address = encode_address(recvtype,signature,mname,call_tree,inference_complete,convention_global_name)
542
543
 
543
- if call_args_tree.size > 1
544
+ fastruby_call_code = if call_args_tree.size > 1
544
545
  value_cast = ( ["VALUE"]*(call_tree[3].size) ).join(",") + ", VALUE, VALUE"
545
546
 
546
- str_called_code_args = call_tree[3][1..-1].map{|subtree| to_c subtree}.join(",")
547
-
548
- caller_code = proc { |name| "
549
- static VALUE #{name}(VALUE param, VALUE pframe) {
547
+ "
550
548
  // call to #{call_tree[2]}
551
549
  #{call_frame_struct_code}
552
550
 
553
- VALUE ret = ((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,call_tree,inference_complete,convention_global_name)})(#{str_recv}, (VALUE)&block, (VALUE)&call_frame, #{str_called_code_args});
551
+ VALUE ret = ((VALUE(*)(#{value_cast}))#{encoded_address})(#{str_recv}, (VALUE)&block, (VALUE)&call_frame, #{str_called_code_args});
554
552
  plocals->call_frame = old_call_frame;
555
553
  return ret;
556
- }
557
554
  "
558
- }
559
-
560
555
  else
561
- caller_code = proc { |name| "
562
- static VALUE #{name}(VALUE param, VALUE pframe) {
556
+ "
563
557
  #{call_frame_struct_code}
564
558
 
565
559
  // call to #{call_tree[2]}
566
- 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);
560
+ VALUE ret = ((VALUE(*)(VALUE,VALUE,VALUE))#{encoded_address})(#{str_recv}, (VALUE)&block, (VALUE)&call_frame);
567
561
  plocals->call_frame = old_call_frame;
568
562
  return ret;
569
- }
570
563
  "
571
- }
572
564
  end
573
565
 
574
566
  inline_block "
575
- if (#{convention_global_name}) {
576
- return #{anonymous_function(&caller_code)}((VALUE)plocals, (VALUE)pframe);
577
- } else {
567
+ if (#{@last_address_name} == 0) {
578
568
  #{funcall_call_code}
569
+ } else {
570
+ if (*#{@last_address_name} == 0) {
571
+ #{funcall_call_code}
572
+ } else {
573
+ #{fastruby_call_code}
574
+ }
579
575
  }
580
576
  "
581
577
  end