diff --git a/integer.rb b/integer.rb index daf11b088f..f2f1e79a5e 100644 --- a/integer.rb +++ b/integer.rb @@ -15,7 +15,7 @@ class Integer # Returns +true+ if +int+ is an even number. def even? Primitive.attr! 'inline' - Primitive.cexpr! 'int_even_p(self)' + Primitive.cexpr! 'rb_int_even_p(self)' end # call-seq: @@ -79,6 +79,6 @@ class Integer # Returns +true+ if +int+ has a zero value. def zero? Primitive.attr! 'inline' - Primitive.cexpr! 'int_zero_p(self)' + Primitive.cexpr! 'rb_int_zero_p(self)' end end diff --git a/internal/numeric.h b/internal/numeric.h index 219e739e7d..87f5559390 100644 --- a/internal/numeric.h +++ b/internal/numeric.h @@ -75,7 +75,6 @@ VALUE rb_int_divmod(VALUE x, VALUE y); VALUE rb_int_and(VALUE x, VALUE y); VALUE rb_int_lshift(VALUE x, VALUE y); VALUE rb_int_div(VALUE x, VALUE y); -VALUE rb_int_abs(VALUE num); VALUE rb_int_odd_p(VALUE num); int rb_int_positive_p(VALUE num); int rb_int_negative_p(VALUE num); @@ -107,6 +106,9 @@ VALUE rb_float_equal(VALUE x, VALUE y); int rb_float_cmp(VALUE x, VALUE y); VALUE rb_float_eql(VALUE x, VALUE y); VALUE rb_fix_aref(VALUE fix, VALUE idx); +VALUE rb_int_zero_p(VALUE num); +VALUE rb_int_even_p(VALUE num); +VALUE rb_int_abs(VALUE num); MJIT_SYMBOL_EXPORT_END static inline bool diff --git a/internal/object.h b/internal/object.h index a05abbf971..d34f498ee1 100644 --- a/internal/object.h +++ b/internal/object.h @@ -35,6 +35,7 @@ VALUE rb_obj_not_equal(VALUE obj1, VALUE obj2); void rb_obj_copy_ivar(VALUE dest, VALUE obj); VALUE rb_false(VALUE obj); VALUE rb_convert_type_with_id(VALUE v, int t, const char* nam, ID mid); +VALUE rb_obj_size(VALUE self, VALUE args, VALUE obj); MJIT_SYMBOL_EXPORT_END static inline void diff --git a/numeric.c b/numeric.c index b883b30440..b59c3198cc 100644 --- a/numeric.c +++ b/numeric.c @@ -794,6 +794,12 @@ int_zero_p(VALUE num) return Qfalse; } +VALUE +rb_int_zero_p(VALUE num) +{ + return int_zero_p(num); +} + /* * call-seq: * num.nonzero? -> self or nil @@ -3250,6 +3256,12 @@ int_even_p(VALUE num) } } +VALUE +rb_int_even_p(VALUE num) +{ + return int_even_p(num); +} + /* * call-seq: * int.allbits?(mask) -> true or false diff --git a/object.c b/object.c index a684927d10..b47635f1fd 100644 --- a/object.c +++ b/object.c @@ -591,7 +591,7 @@ rb_obj_itself(VALUE obj) return obj; } -static VALUE +VALUE rb_obj_size(VALUE self, VALUE args, VALUE obj) { return LONG2FIX(1); diff --git a/tool/mk_builtin_loader.rb b/tool/mk_builtin_loader.rb index 4efdde3023..8f78b660d8 100644 --- a/tool/mk_builtin_loader.rb +++ b/tool/mk_builtin_loader.rb @@ -1,6 +1,8 @@ # Parse built-in script and make rbinc file require 'ripper' +require 'stringio' +require_relative 'ruby_vm/helpers/c_escape' def string_literal(lit, str = []) while lit @@ -207,6 +209,29 @@ def collect_iseq iseq_ary } end +def generate_cexpr(ofile, lineno, line_file, body_lineno, text, locals, func_name) + f = StringIO.new + f.puts '{' + lineno += 1 + locals.reverse_each.with_index{|param, i| + next unless Symbol === param + f.puts "MAYBE_UNUSED(const VALUE) #{param} = rb_vm_lvar(ec, #{-3 - i});" + lineno += 1 + } + f.puts "#line #{body_lineno} \"#{line_file}\"" + lineno += 1 + + f.puts text + lineno += text.count("\n") + 1 + + f.puts "#line #{lineno + 2} \"#{ofile}\"" # TODO: restore line number. + f.puts "}" + f.puts + lineno += 3 + + return lineno, f.string +end + def mk_builtin_header file base = File.basename(file, '.rb') ofile = "#{file}inc" @@ -244,23 +269,10 @@ def mk_builtin_header file inlines.each{|cfunc_name, (body_lineno, text, locals, func_name)| if String === cfunc_name - f.puts "static VALUE #{cfunc_name}(struct rb_execution_context_struct *ec, const VALUE self) {" + f.puts "static VALUE #{cfunc_name}(struct rb_execution_context_struct *ec, const VALUE self)" lineno += 1 - - locals.reverse_each.with_index{|param, i| - next unless Symbol === param - f.puts "MAYBE_UNUSED(const VALUE) #{param} = rb_vm_lvar(ec, #{-3 - i});" - lineno += 1 - } - f.puts "#line #{body_lineno} \"#{line_file}\"" - lineno += 1 - - f.puts text - lineno += text.count("\n") + 1 - - f.puts "#line #{lineno + 2} \"#{ofile}\"" # TODO: restore line number. - f.puts "}" - lineno += 2 + lineno, str = generate_cexpr(ofile, lineno, line_file, body_lineno, text, locals, func_name) + f.write str else # cinit! f.puts "#line #{body_lineno} \"#{line_file}\"" @@ -276,17 +288,32 @@ def mk_builtin_header file f.puts %'static void' f.puts %'mjit_compile_invokebuiltin_for_#{func}(FILE *f, long index)' f.puts %'{' - f.puts %' if (index > 0) {' - f.puts %' fprintf(f, " const unsigned int lnum = GET_ISEQ()->body->local_table_size;\\n");' - f.puts %' fprintf(f, " const VALUE *argv = GET_EP() - lnum - VM_ENV_DATA_SIZE + 1 + %ld;\\n", index);' - f.puts %' }' - f.puts %' else if (index == 0) {' - f.puts %' fprintf(f, " const VALUE *argv = NULL;\\n");' - f.puts %' }' - f.puts %' else {' - f.puts %' fprintf(f, " const VALUE *argv = STACK_ADDR_FROM_TOP(%d);\\n", #{argc});' - f.puts %' }' - f.puts %' fprintf(f, " val = builtin_invoker#{argc}(ec, GET_SELF(), argv, %p);\\n", (const void *)#{cfunc_name});' + if inlines.has_key? cfunc_name + f.puts %' fprintf(f, " MAYBE_UNUSED(VALUE) self = GET_SELF();\\n");' + body_lineno, text, locals, func_name = inlines[cfunc_name] + lineno, str = generate_cexpr(ofile, lineno, line_file, body_lineno, text, locals, func_name) + str.each_line {|i| + f.printf(%' fprintf(f, "%%s", %s);\n', RubyVM::CEscape.rstring2cstr(i.sub(/^return\b/ , ' val ='))) + } + else + decl = ', VALUE' * argc + argv = argc \ + . times \ + . map {|i|", argv[#{i}]"} \ + . join('') + f.puts %' fprintf(f, " typedef VALUE (*func)(rb_execution_context_t *, VALUE#{decl});\\n");' + if argc > 0 + f.puts %' if (index == -1) {' + f.puts %' fprintf(f, " const VALUE *argv = STACK_ADDR_FROM_TOP(%d);\\n", #{argc});' + f.puts %' }' + f.puts %' else {' + f.puts %' fprintf(f, " const unsigned int lnum = GET_ISEQ()->body->local_table_size;\\n");' + f.puts %' fprintf(f, " const VALUE *argv = GET_EP() - lnum - VM_ENV_DATA_SIZE + 1 + %ld;\\n", index);' + f.puts %' }' + end + f.puts %' fprintf(f, " func f = (func)%p\\n;", (const void *)#{cfunc_name});' + f.puts %' fprintf(f, " val = f(ec, GET_SELF()#{argv});\\n");' + end f.puts %'}' f.puts } diff --git a/tool/ruby_vm/helpers/c_escape.rb b/tool/ruby_vm/helpers/c_escape.rb index 3e2bf2e02c..fa3cb8b1aa 100644 --- a/tool/ruby_vm/helpers/c_escape.rb +++ b/tool/ruby_vm/helpers/c_escape.rb @@ -46,7 +46,7 @@ module RubyVM::CEscape # I believe this is the fastest implementation done in pure-ruby. # Constants cached, gsub skips block evaluation, string literal optimized. buf = str.b - buf.gsub! %r/./n, RString2CStr + buf.gsub! %r/./nm, RString2CStr return %'"#{buf}"' end