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.
|
# Returns +true+ if +int+ is an even number.
|
||||||
def even?
|
def even?
|
||||||
Primitive.attr! 'inline'
|
Primitive.attr! 'inline'
|
||||||
Primitive.cexpr! 'int_even_p(self)'
|
Primitive.cexpr! 'rb_int_even_p(self)'
|
||||||
end
|
end
|
||||||
|
|
||||||
# call-seq:
|
# call-seq:
|
||||||
|
@ -79,6 +79,6 @@ class Integer
|
||||||
# Returns +true+ if +int+ has a zero value.
|
# Returns +true+ if +int+ has a zero value.
|
||||||
def zero?
|
def zero?
|
||||||
Primitive.attr! 'inline'
|
Primitive.attr! 'inline'
|
||||||
Primitive.cexpr! 'int_zero_p(self)'
|
Primitive.cexpr! 'rb_int_zero_p(self)'
|
||||||
end
|
end
|
||||||
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_and(VALUE x, VALUE y);
|
||||||
VALUE rb_int_lshift(VALUE x, VALUE y);
|
VALUE rb_int_lshift(VALUE x, VALUE y);
|
||||||
VALUE rb_int_div(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);
|
VALUE rb_int_odd_p(VALUE num);
|
||||||
int rb_int_positive_p(VALUE num);
|
int rb_int_positive_p(VALUE num);
|
||||||
int rb_int_negative_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);
|
int rb_float_cmp(VALUE x, VALUE y);
|
||||||
VALUE rb_float_eql(VALUE x, VALUE y);
|
VALUE rb_float_eql(VALUE x, VALUE y);
|
||||||
VALUE rb_fix_aref(VALUE fix, VALUE idx);
|
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
|
MJIT_SYMBOL_EXPORT_END
|
||||||
|
|
||||||
static inline bool
|
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);
|
void rb_obj_copy_ivar(VALUE dest, VALUE obj);
|
||||||
VALUE rb_false(VALUE obj);
|
VALUE rb_false(VALUE obj);
|
||||||
VALUE rb_convert_type_with_id(VALUE v, int t, const char* nam, ID mid);
|
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
|
MJIT_SYMBOL_EXPORT_END
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
|
12
numeric.c
12
numeric.c
|
@ -794,6 +794,12 @@ int_zero_p(VALUE num)
|
||||||
return Qfalse;
|
return Qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
rb_int_zero_p(VALUE num)
|
||||||
|
{
|
||||||
|
return int_zero_p(num);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* num.nonzero? -> self or nil
|
* 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:
|
* call-seq:
|
||||||
* int.allbits?(mask) -> true or false
|
* int.allbits?(mask) -> true or false
|
||||||
|
|
2
object.c
2
object.c
|
@ -591,7 +591,7 @@ rb_obj_itself(VALUE obj)
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
VALUE
|
||||||
rb_obj_size(VALUE self, VALUE args, VALUE obj)
|
rb_obj_size(VALUE self, VALUE args, VALUE obj)
|
||||||
{
|
{
|
||||||
return LONG2FIX(1);
|
return LONG2FIX(1);
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
# Parse built-in script and make rbinc file
|
# Parse built-in script and make rbinc file
|
||||||
|
|
||||||
require 'ripper'
|
require 'ripper'
|
||||||
|
require 'stringio'
|
||||||
|
require_relative 'ruby_vm/helpers/c_escape'
|
||||||
|
|
||||||
def string_literal(lit, str = [])
|
def string_literal(lit, str = [])
|
||||||
while lit
|
while lit
|
||||||
|
@ -207,6 +209,29 @@ def collect_iseq iseq_ary
|
||||||
}
|
}
|
||||||
end
|
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
|
def mk_builtin_header file
|
||||||
base = File.basename(file, '.rb')
|
base = File.basename(file, '.rb')
|
||||||
ofile = "#{file}inc"
|
ofile = "#{file}inc"
|
||||||
|
@ -244,23 +269,10 @@ def mk_builtin_header file
|
||||||
|
|
||||||
inlines.each{|cfunc_name, (body_lineno, text, locals, func_name)|
|
inlines.each{|cfunc_name, (body_lineno, text, locals, func_name)|
|
||||||
if String === cfunc_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
|
lineno += 1
|
||||||
|
lineno, str = generate_cexpr(ofile, lineno, line_file, body_lineno, text, locals, func_name)
|
||||||
locals.reverse_each.with_index{|param, i|
|
f.write str
|
||||||
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
|
|
||||||
else
|
else
|
||||||
# cinit!
|
# cinit!
|
||||||
f.puts "#line #{body_lineno} \"#{line_file}\""
|
f.puts "#line #{body_lineno} \"#{line_file}\""
|
||||||
|
@ -276,17 +288,32 @@ def mk_builtin_header file
|
||||||
f.puts %'static void'
|
f.puts %'static void'
|
||||||
f.puts %'mjit_compile_invokebuiltin_for_#{func}(FILE *f, long index)'
|
f.puts %'mjit_compile_invokebuiltin_for_#{func}(FILE *f, long index)'
|
||||||
f.puts %'{'
|
f.puts %'{'
|
||||||
f.puts %' if (index > 0) {'
|
if inlines.has_key? cfunc_name
|
||||||
f.puts %' fprintf(f, " const unsigned int lnum = GET_ISEQ()->body->local_table_size;\\n");'
|
f.puts %' fprintf(f, " MAYBE_UNUSED(VALUE) self = GET_SELF();\\n");'
|
||||||
f.puts %' fprintf(f, " const VALUE *argv = GET_EP() - lnum - VM_ENV_DATA_SIZE + 1 + %ld;\\n", index);'
|
body_lineno, text, locals, func_name = inlines[cfunc_name]
|
||||||
f.puts %' }'
|
lineno, str = generate_cexpr(ofile, lineno, line_file, body_lineno, text, locals, func_name)
|
||||||
f.puts %' else if (index == 0) {'
|
str.each_line {|i|
|
||||||
f.puts %' fprintf(f, " const VALUE *argv = NULL;\\n");'
|
f.printf(%' fprintf(f, "%%s", %s);\n', RubyVM::CEscape.rstring2cstr(i.sub(/^return\b/ , ' val =')))
|
||||||
f.puts %' }'
|
}
|
||||||
f.puts %' else {'
|
else
|
||||||
f.puts %' fprintf(f, " const VALUE *argv = STACK_ADDR_FROM_TOP(%d);\\n", #{argc});'
|
decl = ', VALUE' * argc
|
||||||
f.puts %' }'
|
argv = argc \
|
||||||
f.puts %' fprintf(f, " val = builtin_invoker#{argc}(ec, GET_SELF(), argv, %p);\\n", (const void *)#{cfunc_name});'
|
. 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 %'}'
|
||||||
f.puts
|
f.puts
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ module RubyVM::CEscape
|
||||||
# I believe this is the fastest implementation done in pure-ruby.
|
# I believe this is the fastest implementation done in pure-ruby.
|
||||||
# Constants cached, gsub skips block evaluation, string literal optimized.
|
# Constants cached, gsub skips block evaluation, string literal optimized.
|
||||||
buf = str.b
|
buf = str.b
|
||||||
buf.gsub! %r/./n, RString2CStr
|
buf.gsub! %r/./nm, RString2CStr
|
||||||
return %'"#{buf}"'
|
return %'"#{buf}"'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue