fastruby 0.0.15 → 0.0.16

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