mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
inline Primitive.cexpr!
We can obtain the verbatim source code of Primitive.cexpr!. Why not paste that content into the JITed program.
This commit is contained in:
parent
f66e0212ef
commit
9721f477c7
Notes:
git
2020-07-13 08:56:53 +09:00
7 changed files with 74 additions and 32 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
12
numeric.c
12
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
|
||||
|
|
2
object.c
2
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);
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue