fastruby 0.0.15 → 0.0.16

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.
data/CHANGELOG CHANGED
@@ -1,3 +1,7 @@
1
+ 0.0.16 Limited (see known issues on README) support for ruby1.9-p180 (tested with rvm)
2
+
3
+ Support for ruby1.8-p334 (tested with rvm)
4
+
1
5
  0.0.15 Support for continuation objects and callcc
2
6
 
3
7
  Fixed fastruby protocol to support unlimited number of arguments from ruby
data/README CHANGED
@@ -57,6 +57,8 @@ I will stabilize the API and document it for next releases. I promise
57
57
 
58
58
  == Known Limitations & Issues
59
59
 
60
+ * fastruby now works with ruby1.9, but features specific to ruby1.9 (such fibers and new hash notation) will not work or will work with unexpected behaviour
61
+ * fastruby on ruby1.8 is faster than ruby1.8 on a few cases (see benchmarks) but is slower than ruby1.9
60
62
  * callcc is not supported, it works but using it may result in unexpected behaviour
61
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 is pretty fast)
62
64
  * replacement of methods using identical code strings will work, but it will generate duplicated objects on the cache each time te snippet run
data/Rakefile CHANGED
@@ -7,13 +7,13 @@ 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.15'
10
+ s.version = '0.0.16'
11
11
  s.author = 'Dario Seminara'
12
12
  s.email = 'robertodarioseminara@gmail.com'
13
13
  s.platform = Gem::Platform::RUBY
14
14
  s.summary = 'fast execution of ruby code'
15
15
  s.homepage = "http://github.com/tario/fastruby"
16
- s.add_dependency "RubyInline", "= 3.9.0"
16
+ s.add_dependency "RubyInline", "= 3.11.0"
17
17
  s.add_dependency "ruby_parser", "= 2.0.6"
18
18
  s.has_rdoc = true
19
19
  s.extra_rdoc_files = [ 'README' ]
@@ -1,7 +1,17 @@
1
1
  require 'mkmf'
2
2
  dir_config('fastruby_base')
3
3
  CONFIG['CC'] = 'gcc'
4
- create_makefile('fastruby_base')
5
4
 
5
+ ruby_version = Config::CONFIG["ruby_version"]
6
+ ruby_version = ruby_version.split(".")[0..1].join(".")
6
7
 
8
+ if ruby_version == "1.8"
9
+ $CFLAGS = $CFLAGS + " -DRUBY_1_8"
10
+ elsif ruby_version == "1.9"
11
+ $CFLAGS = $CFLAGS + " -DRUBY_1_9"
12
+ else
13
+ print "ERROR: unknown ruby version: #{ruby_version}\n"
14
+ print "try passing the rubyversion by argument (1.8 or 1.9)\n"
15
+ end
7
16
 
17
+ create_makefile('fastruby_base')
@@ -1,6 +1,10 @@
1
1
  #include "ruby.h"
2
+ #include "setjmp.h"
3
+
4
+ #ifdef RUBY_1_8
2
5
  #include "node.h"
3
6
  #include "env.h"
7
+ #endif
4
8
 
5
9
  VALUE rb_cStackChunk;
6
10
  VALUE rb_cFastRubyThreadData;
@@ -26,6 +30,47 @@ struct FASTRUBYTHREADDATA {
26
30
  void* last_plocals;
27
31
  };
28
32
 
33
+ #ifdef RUBY_1_8
34
+ #define _RARRAY_LEN(x) (RARRAY(x)->len)
35
+ #define _RSTRING_PTR(x) (RSTRING(x)->ptr)
36
+ #endif
37
+
38
+ #ifdef RUBY_1_9
39
+
40
+ void* rb_method_entry(VALUE klass, ID id);
41
+ void* rb_global_entry(ID id);
42
+
43
+ typedef struct RNode {
44
+ unsigned long flags;
45
+ char *nd_file;
46
+ union {
47
+ struct RNode *node;
48
+ ID id;
49
+ VALUE value;
50
+ VALUE (*cfunc)(ANYARGS);
51
+ ID *tbl;
52
+ } u1;
53
+ union {
54
+ struct RNode *node;
55
+ ID id;
56
+ long argc;
57
+ VALUE value;
58
+ } u2;
59
+ union {
60
+ struct RNode *node;
61
+ ID id;
62
+ long state;
63
+ struct rb_global_entry *entry;
64
+ long cnt;
65
+ VALUE value;
66
+ } u3;
67
+ } NODE;
68
+
69
+
70
+ #define _RARRAY_LEN(x) RARRAY_LEN(x)
71
+ #define _RSTRING_PTR(x) RSTRING_PTR(x)
72
+ #endif
73
+
29
74
  struct METHOD {
30
75
  VALUE klass, rklass;
31
76
  VALUE recv;
@@ -235,8 +280,7 @@ static VALUE clear_method_hash_addresses(VALUE klass,VALUE rb_method_hash) {
235
280
  VALUE rb_values = rb_funcall(rb_method_hash, rb_intern("values"),0);
236
281
  void** address;
237
282
  int i;
238
-
239
- for (i = 0; i < RARRAY(rb_values)->len; i++) {
283
+ for (i = 0; i < _RARRAY_LEN(rb_values); i++) {
240
284
  address = (void**)FIX2LONG(rb_ary_entry(rb_values,i));
241
285
  *address = 0;
242
286
  }
@@ -246,7 +290,7 @@ static VALUE clear_method_hash_addresses(VALUE klass,VALUE rb_method_hash) {
246
290
  }
247
291
 
248
292
  static VALUE has_fastruby_function(VALUE self, VALUE rb_method_hash, VALUE mname) {
249
- ID id = rb_intern(RSTRING(mname)->ptr);
293
+ ID id = rb_intern(_RSTRING_PTR(mname));
250
294
  VALUE tmp = rb_hash_aref(rb_method_hash, LONG2FIX(id));
251
295
 
252
296
  if (tmp != Qnil) {
@@ -18,7 +18,6 @@ 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 "fastruby/inline_extension"
22
21
  require "fastruby/method_extension"
23
22
  require "fastruby/logging"
24
23
  require "fastruby/getlocals"
@@ -58,6 +57,7 @@ module FastRuby
58
57
  require "fastruby/translator/translator"
59
58
  require "rubygems"
60
59
  require "inline"
60
+ require "fastruby/inline_extension"
61
61
 
62
62
  context = FastRuby::Context.new
63
63
  context.locals = locals
@@ -105,10 +105,23 @@ module FastRuby
105
105
 
106
106
  begin
107
107
 
108
+ unless $inline_extra_flags
109
+ $inline_extra_flags = true
110
+
111
+ ['CFLAGS','CXXFLAGS','OPTFLAGS','cflags','cxxflags','optflags'].each do |name|
112
+ RbConfig::CONFIG[name].gsub!(/\-O\d/,"-O1") if RbConfig::CONFIG[name]
113
+ end
114
+
115
+ if RUBY_VERSION =~ /^1\.8/
116
+ RbConfig::CONFIG['CFLAGS'] << " -DRUBY_1_8 -Wno-clobbered"
117
+ elsif RUBY_VERSION =~ /^1\.9/
118
+ RbConfig::CONFIG['CFLAGS'] << " -DRUBY_1_9 -Wno-clobbered"
119
+ end
120
+ end
121
+
108
122
  @owner.class_eval do
109
123
  inline :C do |builder|
110
124
  builder.inc << context.extra_code
111
- builder.include "<node.h>"
112
125
  builder.init_extra = context.init_extra
113
126
 
114
127
  def builder.generate_ext
@@ -18,7 +18,7 @@ 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 "sha1"
21
+ require "digest"
22
22
  require "fileutils"
23
23
 
24
24
  module FastRuby
@@ -37,7 +37,7 @@ module FastRuby
37
37
  end
38
38
 
39
39
  def hash_snippet(snippet, addition)
40
- SHA1.hexdigest(snippet + addition)
40
+ Digest::SHA1.hexdigest(snippet + addition)
41
41
  end
42
42
 
43
43
  def insert(hash,path)
@@ -21,67 +21,20 @@ along with fastruby. if not, see <http://www.gnu.org/licenses/>.
21
21
  module Inline
22
22
  class C
23
23
  attr_reader :inc
24
-
25
- def generate(src, options={})
26
- options = {:expand_types=>options} unless Hash === options
27
-
28
- expand_types = options[:expand_types]
29
- singleton = options[:singleton]
30
- result = self.strip_comments(src)
31
-
32
- signature = parse_signature(src, !expand_types)
33
- function_name = signature['name']
34
- method_name = options[:method_name]
35
- method_name ||= test_to_normal function_name
36
- return_type = signature['return']
37
- arity = options[:arity] || signature['arity']
38
-
39
- raise ArgumentError, "too many arguments" if arity > MAGIC_ARITY_THRESHOLD
40
-
41
- if expand_types then
42
- prefix = "static VALUE #{function_name}("
43
- if arity <= MAGIC_ARITY then
44
- prefix += "int argc, VALUE *argv, VALUE self"
45
- else
46
- prefix += "VALUE self"
47
- prefix += signature['args'].map { |arg, type| ", VALUE _#{arg}"}.join
48
- end
49
- prefix += ") {\n"
50
- prefix += signature['args'].map { |arg, type|
51
- " #{type} #{arg} = #{ruby2c(type)}(_#{arg});\n"
52
- }.join
53
-
54
- # replace the function signature (hopefully) with new sig (prefix)
55
- result.sub!(/[^;\/\"\>]+#{function_name}\s*\([^\{]+\{/, "\n" + prefix)
56
- result.sub!(/\A\n/, '') # strip off the \n in front in case we added it
57
- unless return_type == "void" then
58
- raise SyntaxError, "Couldn't find return statement for #{function_name}" unless
59
- result =~ /return/
60
- else
61
- result.sub!(/\s*\}\s*\Z/, "\nreturn Qnil;\n}")
62
- end
63
- else
64
- prefix = "static #{return_type} #{function_name}("
65
- result.sub!(/[^;\/\"\>]+#{function_name}\s*\(/, prefix)
66
- result.sub!(/\A\n/, '') # strip off the \n in front in case we added it
24
+
25
+ def module_name
26
+ unless defined? @module_name then
27
+ module_name = if @mod.name
28
+ @mod.name.gsub('::','__')
29
+ else
30
+ rand(1000000000000000).to_s
31
+ end
32
+ md5 = Digest::MD5.new
33
+ @sig.keys.sort_by { |x| x.to_s }.each { |m| md5 << m.to_s }
34
+ @module_name = "Inline_#{module_name}_#{md5}"
67
35
  end
68
-
69
- delta = if result =~ /\A(static.*?\{)/m then
70
- $1.split(/\n/).size
71
- else
72
- warn "WAR\NING: Can't find signature in #{result.inspect}\n" unless $TESTING
73
- 0
74
- end
75
-
76
- file, line = caller[1].split(/:/)
77
- result = "# line #{line.to_i + delta} \"#{file}\"\n" + result unless $DEBUG and not $TESTING
78
-
79
- @src << result
80
- @sig[function_name] = [arity,singleton,method_name]
81
-
82
- return result if $TESTING
83
- end # def generate
84
-
36
+ @module_name
37
+ end
85
38
  end
86
39
  end
87
40
 
@@ -81,7 +81,7 @@ class Object
81
81
 
82
82
  return unless tree
83
83
  method_name = "_anonymous_" + rand(100000000000).to_s
84
- Object.execute_tree(FastRuby.encapsulate_tree(tree,method_name), :main => method_name, :self => self, :snippet_hash => snippet_hash, *[options_hash])
84
+ Object.execute_tree(FastRuby.encapsulate_tree(tree,method_name), {:main => method_name, :self => self, :snippet_hash => snippet_hash}.merge(options_hash))
85
85
 
86
86
  else
87
87
 
data/lib/fastruby/self ADDED
@@ -0,0 +1,82 @@
1
+ translator/modules/variable.rb 27| "rb_cvar_get(CLASS_OF(plocals->self) != rb_cClass ? CLASS_OF(plocals->self) : plocals->self,#{intern_num tree[1]})"
2
+ translator/modules/variable.rb 31| "__rb_cvar_set(CLASS_OF(plocals->self) != rb_cClass ? CLASS_OF(plocals->self) : plocals->self,#{intern_num tree[1]},#{to_c tree[2]},Qfalse)"
3
+ translator/modules/variable.rb 55| "rb_const_get(CLASS_OF(plocals->self), #{intern_num(tree[1])})"
4
+ translator/modules/variable.rb 170| "rb_ivar_defined(plocals->self,#{intern_num tree[1][1]}) ? #{literal_value "instance-variable"} : Qnil"
5
+ translator/modules/defn.rb 46| rb_define_method(plocals->self, #{method_name.to_s.inspect}, #{anonymous_method_name}, -1);
6
+ translator/modules/defn.rb 48| #{global_klass_variable} = plocals->self;
7
+ translator/modules/method_group.rb 115| plocals->parent_locals = LONG2FIX(frame.thread_data->last_plocals);
8
+ translator/modules/method_group.rb 120| plocals->active = Qtrue;
9
+ translator/modules/method_group.rb 121| plocals->self = self;
10
+ translator/modules/method_group.rb 122| plocals->targetted = Qfalse;
11
+ translator/modules/method_group.rb 123| plocals->call_frame = LONG2FIX(0);
12
+ translator/modules/method_group.rb 134| plocals->active = Qfalse;
13
+ translator/modules/iter.rb 107| str_arg_initialization << "plocals->#{args_tree[1]} = arg;"
14
+ translator/modules/iter.rb 111| plocals->#{args_tree[1]} = arg;
15
+ translator/modules/iter.rb 113| plocals->#{args_tree[1]} = rb_ary_entry(arg,0);
16
+ translator/modules/iter.rb 138| str_arg_initialization << "plocals->#{arguments[i].last} = rb_ary_entry(arg,#{i});\n"
17
+ translator/modules/iter.rb 140| str_arg_initialization << "plocals->#{arg.last.last} = rb_ary_new2(_RARRAY_LEN(arg)-#{i});\n
18
+ translator/modules/iter.rb 144| rb_ary_store(plocals->#{arg.last.last},i-#{i},rb_ary_entry(arg,i));
19
+ translator/modules/iter.rb 156| str_recv = "plocals->self" unless recv_tree
20
+ translator/modules/iter.rb 209| str_recv = "plocals->self" unless recv_tree
21
+ translator/modules/iter.rb 286| if (plocals->targetted == 1) {
22
+ translator/modules/iter.rb 341| if (plocals->targetted == 1) {
23
+ translator/modules/iter.rb 342| if (plocals->active == Qfalse) {
24
+ translator/modules/iter.rb 451| fastruby_str_arg_initialization = "plocals->#{args_tree[1]} = argv[0];"
25
+ translator/modules/iter.rb 458| fastruby_str_arg_initialization << "plocals->#{arg.last} = #{i} < argc ? argv[#{i}] : Qnil;\n"
26
+ translator/modules/iter.rb 460| fastruby_str_arg_initialization << "plocals->#{arg.last.last} = rb_ary_new2(#{arguments.size-1-i});\n
27
+ translator/modules/iter.rb 464| rb_ary_store(plocals->#{arg.last.last},i-#{i},argv[i]);
28
+ translator/modules/iter.rb 513| str_recv = "plocals->self"
29
+ translator/modules/iter.rb 537| VALUE old_call_frame = plocals->call_frame;
30
+ translator/modules/iter.rb 538| plocals->call_frame = LONG2FIX(&call_frame);
31
+ translator/modules/iter.rb 551| plocals->call_frame = old_call_frame;
32
+ translator/modules/iter.rb 561| pframe->next_recv = #{recv_tree ? to_c(recv_tree) : "plocals->self"};
33
+ translator/modules/iter.rb 646| current_plocals->active = Qfalse;
34
+ translator/modules/iter.rb 647| current_plocals = (typeof(current_plocals))FIX2LONG(current_plocals->parent_locals);
35
+ translator/modules/iter.rb 657| current_plocals->active = Qtrue;
36
+ translator/modules/iter.rb 658| current_plocals = (typeof(current_plocals))FIX2LONG(current_plocals->parent_locals);
37
+ translator/modules/iter.rb 684| plocals->call_frame = old_call_frame;
38
+ translator/modules/iter.rb 693| plocals->call_frame = old_call_frame;
39
+ translator/modules/block.rb 36| if (FIX2LONG(plocals->block_function_address) == 0) {
40
+ translator/modules/block.rb 39| return ((VALUE(*)(int,VALUE*,VALUE,VALUE))FIX2LONG(plocals->block_function_address))(size, block_args, FIX2LONG(plocals->block_function_param), (VALUE)pframe);
41
+ translator/modules/nonlocal.rb 27| plocals->return_value = #{to_c(tree[1])};
42
+ translator/modules/nonlocal.rb 28| plocals->targetted = 1;
43
+ translator/modules/nonlocal.rb 41| target_frame_ = (void*)FIX2LONG(plocals->call_frame);
44
+ translator/modules/nonlocal.rb 47| plocals->call_frame = LONG2FIX(0);
45
+ translator/modules/nonlocal.rb 60| target_frame_ = (void*)FIX2LONG(plocals->call_frame);
46
+ translator/translator.rb 213| VALUE old_call_frame = plocals->call_frame;
47
+ translator/translator.rb 214| plocals->call_frame = LONG2FIX(&call_frame);
48
+ translator/translator.rb 226| plocals->call_frame = old_call_frame;
49
+ translator/translator.rb 232| plocals->call_frame = old_call_frame;
50
+ translator/translator.rb 243| plocals->call_frame = old_call_frame;
51
+ translator/translator.rb 398| plocals->parent_locals = LONG2FIX(frame.thread_data->last_plocals);
52
+ translator/translator.rb 402| plocals->active = Qtrue;
53
+ translator/translator.rb 403| plocals->targetted = Qfalse;
54
+ translator/translator.rb 404| plocals->pframe = LONG2FIX(&frame);
55
+ translator/translator.rb 420| plocals->active = Qfalse;
56
+ translator/translator.rb 422| return plocals->return_value;
57
+ translator/translator.rb 425| plocals->self = self;
58
+ translator/translator.rb 430| "plocals->#{arg} = #{arg};\n"
59
+ translator/translator.rb 433| plocals->block_function_address = LONG2FIX(0);
60
+ translator/translator.rb 434| plocals->block_function_param = LONG2FIX(Qnil);
61
+ translator/translator.rb 435| plocals->call_frame = LONG2FIX(0);
62
+ translator/translator.rb 445| plocals->active = Qfalse;
63
+ translator/translator.rb 525| "plocals->#{arg} = argv[#{i}];\n"
64
+ translator/translator.rb 547| plocals->#{splat_arg.to_s.gsub("*","")} = rb_ary_new3(0);
65
+ translator/translator.rb 551| plocals->#{splat_arg.to_s.gsub("*","")} = rb_ary_new4(
66
+ translator/translator.rb 570| plocals->#{block_argument.to_s.gsub("&","")} = #{to_c FastRuby::FastRubySexp.from_sexp(proc_reyield_block_tree)};
67
+ translator/translator.rb 616| plocals->parent_locals = LONG2FIX(frame.thread_data->last_plocals);
68
+ translator/translator.rb 621| plocals->active = Qtrue;
69
+ translator/translator.rb 622| plocals->targetted = Qfalse;
70
+ translator/translator.rb 623| plocals->pframe = LONG2FIX(&frame);
71
+ translator/translator.rb 624| plocals->call_frame = LONG2FIX(0);
72
+ translator/translator.rb 633| plocals->active = Qfalse;
73
+ translator/translator.rb 642| if (plocals->targetted == Qfalse || aux != FASTRUBY_TAG_RETURN) {
74
+ translator/translator.rb 650| return plocals->return_value;
75
+ translator/translator.rb 653| plocals->self = self;
76
+ translator/translator.rb 659| plocals->block_function_address = LONG2FIX(pblock->block_function_address);
77
+ translator/translator.rb 660| plocals->block_function_param = LONG2FIX(pblock->block_function_param);
78
+ translator/translator.rb 662| plocals->block_function_address = LONG2FIX(0);
79
+ translator/translator.rb 663| plocals->block_function_param = LONG2FIX(Qnil);
80
+ translator/translator.rb 674| plocals->active = Qfalse;
81
+ translator/translator.rb 693| "plocals->"
82
+ translator/translator.rb 759| return "FIX2LONG(plocals->block_function_address) == 0 ? Qfalse : Qtrue"
@@ -26,12 +26,20 @@ class Object
26
26
  end
27
27
  end
28
28
 
29
+ module FastRuby
30
+ class FastRubySexp
31
+ def self.from_sexp(value)
32
+ ary = FastRuby::FastRubySexp.new
33
+ value.each do |x|
34
+ ary << x.to_fastruby_sexp
35
+ end
36
+ ary
37
+ end
38
+ end
39
+ end
40
+
29
41
  class Sexp
30
42
  def to_fastruby_sexp
31
- ary = FastRuby::FastRubySexp.new
32
- each do |x|
33
- ary << x.to_fastruby_sexp
34
- end
35
- ary
43
+ FastRuby::FastRubySexp.from_sexp(self)
36
44
  end
37
45
  end
@@ -49,7 +49,7 @@ module FastRuby
49
49
  VALUE splat_array = #{to_c(splat_arg[1])};
50
50
 
51
51
  if (CLASS_OF(splat_array) == rb_cArray) {
52
- VALUE block_args[RARRAY(splat_array)->len + #{tree.size}];
52
+ VALUE block_args[_RARRAY_LEN(splat_array) + #{tree.size}];
53
53
  int i;
54
54
  #{
55
55
  (0..tree.size-3).map{|i|
@@ -57,11 +57,11 @@ module FastRuby
57
57
  }.join(";\n")
58
58
  };
59
59
 
60
- for (i=0; i<RARRAY(splat_array)->len; i++) {
60
+ for (i=0; i<_RARRAY_LEN(splat_array); i++) {
61
61
  block_args[i+#{tree.size-2}] = rb_ary_entry(splat_array,i);
62
62
  }
63
63
 
64
- return #{anonymous_function(&block_code)}((VALUE)pframe, block_args, RARRAY(splat_array)->len + #{tree.size-2});
64
+ return #{anonymous_function(&block_code)}((VALUE)pframe, block_args, _RARRAY_LEN(splat_array) + #{tree.size-2});
65
65
  } else {
66
66
  VALUE block_args[1+#{tree.size}];
67
67
  #{
@@ -86,7 +86,7 @@ module FastRuby
86
86
  }
87
87
 
88
88
  int argc = #{args.size-2};
89
- VALUE argv[#{args.size} + RARRAY(array)->len];
89
+ VALUE argv[#{args.size} + _RARRAY_LEN(array)];
90
90
 
91
91
  #{
92
92
  i = -1
@@ -96,7 +96,7 @@ module FastRuby
96
96
  }.join(";\n")
97
97
  };
98
98
 
99
- int array_len = RARRAY(array)->len;
99
+ int array_len = _RARRAY_LEN(array);
100
100
 
101
101
  int i;
102
102
  for (i=0; i<array_len;i++) {
@@ -41,7 +41,9 @@ module FastRuby
41
41
  alt_options.delete(:main)
42
42
 
43
43
  inline_block "
44
- rb_define_method(plocals->self, #{method_name.to_s.inspect}, #{anonymous_method_name}, -1 );
44
+
45
+ usleep(0);
46
+ rb_define_method(plocals->self, #{method_name.to_s.inspect}, #{anonymous_method_name}, -1);
45
47
 
46
48
  #{global_klass_variable} = plocals->self;
47
49
  // set tree
@@ -103,22 +103,39 @@ module FastRuby
103
103
 
104
104
  if not args_tree
105
105
  elsif args_tree.first == :lasgn
106
- str_arg_initialization << "plocals->#{args_tree[1]} = arg;"
106
+ if RUBY_VERSION =~ /^1\.8/
107
+ str_arg_initialization << "plocals->#{args_tree[1]} = arg;"
108
+ elsif RUBY_VERSION =~ /^1\.9/
109
+ str_arg_initialization << "
110
+ if (TYPE(arg) != T_ARRAY) {
111
+ plocals->#{args_tree[1]} = arg;
112
+ } else {
113
+ plocals->#{args_tree[1]} = rb_ary_entry(arg,0);
114
+ }
115
+ "
116
+ end
107
117
  elsif args_tree.first == :masgn
108
118
 
109
- str_arg_initialization << "
110
- {
111
- if (TYPE(arg) != T_ARRAY) {
112
- if (arg != Qnil) {
119
+ if RUBY_VERSION =~ /^1\.8/
120
+ str_arg_initialization << "
121
+ {
122
+ if (TYPE(arg) != T_ARRAY) {
123
+ if (arg != Qnil) {
124
+ arg = rb_ary_new4(1,&arg);
125
+ } else {
126
+ arg = rb_ary_new2(0);
127
+ }
128
+ } else if (_RARRAY_LEN(arg) <= 1) {
113
129
  arg = rb_ary_new4(1,&arg);
114
- } else {
115
- arg = rb_ary_new2(0);
116
130
  }
117
- } else if (RARRAY(arg)->len <= 1) {
118
- arg = rb_ary_new4(1,&arg);
119
131
  }
120
- }
121
- "
132
+ "
133
+ elsif RUBY_VERSION =~ /^1\.9/
134
+ str_arg_initialization << "
135
+ {
136
+ }
137
+ "
138
+ end
122
139
 
123
140
  arguments = args_tree[1][1..-1]
124
141
 
@@ -127,10 +144,10 @@ module FastRuby
127
144
  if arg[0] == :lasgn
128
145
  str_arg_initialization << "plocals->#{arguments[i].last} = rb_ary_entry(arg,#{i});\n"
129
146
  elsif arg[0] == :splat
130
- str_arg_initialization << "plocals->#{arg.last.last} = rb_ary_new2(RARRAY(arg)->len-#{i});\n
147
+ str_arg_initialization << "plocals->#{arg.last.last} = rb_ary_new2(_RARRAY_LEN(arg)-#{i});\n
131
148
 
132
149
  int i;
133
- for (i=#{i};i<RARRAY(arg)->len;i++){
150
+ for (i=#{i};i<_RARRAY_LEN(arg);i++){
134
151
  rb_ary_store(plocals->#{arg.last.last},i-#{i},rb_ary_entry(arg,i));
135
152
  }
136
153
  "
@@ -158,7 +175,7 @@ module FastRuby
158
175
  }
159
176
 
160
177
  int argc = #{call_args_tree.size-2};
161
- VALUE argv[#{call_args_tree.size} + RARRAY(array)->len];
178
+ VALUE argv[#{call_args_tree.size} + _RARRAY_LEN(array)];
162
179
 
163
180
  #{
164
181
  i = -1
@@ -168,7 +185,7 @@ module FastRuby
168
185
  }.join(";\n")
169
186
  };
170
187
 
171
- int array_len = RARRAY(array)->len;
188
+ int array_len = _RARRAY_LEN(array);
172
189
 
173
190
  int i;
174
191
  for (i=0; i<array_len;i++) {
@@ -239,10 +256,35 @@ module FastRuby
239
256
  }
240
257
 
241
258
  end
259
+
260
+ argument_array_read = "
261
+ VALUE arg;
262
+ #{
263
+ # TODO: access directly to argc and argv for optimal execution
264
+ if RUBY_VERSION =~ /^1\.9/
265
+ "
266
+ if (TYPE(arg_) == T_ARRAY) {
267
+ if (_RARRAY_LEN(arg_) <= 1) {
268
+ arg = rb_ary_new4(argc,argv);
269
+ } else {
270
+ arg = arg_;
271
+ }
272
+ } else {
273
+ arg = rb_ary_new4(argc,argv);
274
+ }
275
+ "
276
+ else
277
+ "arg = arg_;"
278
+ end
279
+ }
280
+ "
281
+
242
282
 
243
283
  rb_funcall_block_code_with_lambda = proc { |name| "
244
- static VALUE #{name}(VALUE arg, VALUE _plocals) {
284
+ static VALUE #{name}(VALUE arg_, VALUE _plocals, int argc, VALUE* argv) {
245
285
  // block for call to #{call_tree[2]}
286
+ #{argument_array_read}
287
+
246
288
  VALUE last_expression = Qnil;
247
289
 
248
290
  #{@frame_struct} frame;
@@ -299,8 +341,10 @@ module FastRuby
299
341
  }
300
342
 
301
343
  rb_funcall_block_code_proc_new = proc { |name| "
302
- static VALUE #{name}(VALUE arg, VALUE _plocals) {
344
+ static VALUE #{name}(VALUE arg_, VALUE _plocals, int argc, VALUE* argv) {
303
345
  // block for call to #{call_tree[2]}
346
+ #{argument_array_read}
347
+
304
348
  VALUE last_expression = Qnil;
305
349
 
306
350
  #{@frame_struct} frame;
@@ -353,8 +397,10 @@ module FastRuby
353
397
 
354
398
 
355
399
  rb_funcall_block_code = proc { |name| "
356
- static VALUE #{name}(VALUE arg, VALUE _plocals) {
400
+ static VALUE #{name}(VALUE arg_, VALUE _plocals, int argc, VALUE* argv) {
357
401
  // block for call to #{call_tree[2]}
402
+ #{argument_array_read}
403
+
358
404
  VALUE last_expression = Qnil;
359
405
 
360
406
  #{@frame_struct} frame;
@@ -391,7 +437,14 @@ module FastRuby
391
437
  }
392
438
 
393
439
  rb_funcall_block_code_callcc = proc { |name| "
394
- static VALUE #{name}(VALUE arg, VALUE _plocals) {
440
+ static VALUE #{name}(VALUE arg, VALUE _plocals, int argc, VALUE* argv) {
441
+ #{
442
+ # TODO: access directly to argc and argv for optimal execution
443
+ if RUBY_VERSION =~ /^1\.9/
444
+ "arg = rb_ary_new4(argc,argv);"
445
+ end
446
+ }
447
+
395
448
  // block for call to #{call_tree[2]}
396
449
  VALUE last_expression = Qnil;
397
450
 
@@ -419,7 +472,7 @@ module FastRuby
419
472
  }
420
473
  }
421
474
 
422
- if (rb_obj_is_kind_of(arg,rb_cCont)) {
475
+ if (rb_obj_is_kind_of(arg, rb_const_get(rb_cObject, #{intern_num :Continuation}))) {
423
476
  struct FASTRUBYTHREADDATA* thread_data = frame.thread_data;
424
477
  rb_ivar_set(arg,#{intern_num :__stack_chunk},thread_data->rb_stack_chunk);
425
478
  }
@@ -549,8 +602,12 @@ module FastRuby
549
602
  VALUE saved_rb_stack_chunk = Qnil;
550
603
 
551
604
  pframe->next_recv = #{recv_tree ? to_c(recv_tree) : "plocals->self"};
552
-
605
+ #ifdef RUBY_1_8
553
606
  NODE* node = rb_method_node(CLASS_OF(pframe->next_recv), #{intern_num mname});
607
+ #endif
608
+ #ifdef RUBY_1_9
609
+ void* node = rb_method_entry(CLASS_OF(pframe->next_recv), #{intern_num mname});
610
+ #endif
554
611
 
555
612
  if (node == #{@callcc_node_gvar}) {
556
613
 
@@ -586,7 +643,6 @@ module FastRuby
586
643
  frame_call(
587
644
  protected_block(inline_block("
588
645
 
589
- NODE* node = rb_method_node(CLASS_OF(pframe->next_recv), #{intern_num mname});
590
646
  void* caller_func;
591
647
  void* block_func;
592
648
  typeof(plocals) current_plocals;
@@ -594,6 +650,13 @@ module FastRuby
594
650
  if (pframe->thread_data == 0) pframe->thread_data = rb_current_thread_data();
595
651
  void* last_plocals = pframe->thread_data->last_plocals;
596
652
 
653
+ #ifdef RUBY_1_8
654
+ NODE* node = rb_method_node(CLASS_OF(pframe->next_recv), #{intern_num mname});
655
+ #endif
656
+ #ifdef RUBY_1_9
657
+ void* node = rb_method_entry(CLASS_OF(pframe->next_recv), #{intern_num mname});
658
+ #endif
659
+
597
660
  if (
598
661
  node == #{@proc_node_gvar} ||
599
662
  node == #{@lambda_node_gvar}
@@ -159,7 +159,11 @@ module FastRuby
159
159
  elsif nt == :const
160
160
  "rb_const_defined(rb_cObject, #{intern_num tree[1][1]}) ? #{literal_value "constant"} : Qnil"
161
161
  elsif nt == :call
162
- "rb_method_node(CLASS_OF(#{to_c tree[1][1]}), #{intern_num tree[1][2]}) ? #{literal_value "method"} : Qnil"
162
+ if RUBY_VERSION =~ /^1\.8/
163
+ "rb_method_node(CLASS_OF(#{to_c tree[1][1]}), #{intern_num tree[1][2]}) ? #{literal_value "method"} : Qnil"
164
+ else
165
+ "rb_method_entry(CLASS_OF(#{to_c tree[1][1]}), #{intern_num tree[1][2]}) ? #{literal_value "method"} : Qnil"
166
+ end
163
167
  elsif nt == :yield
164
168
  "rb_block_given_p() ? #{literal_value "yield"} : Qnil"
165
169
  elsif nt == :ivar