diff options
author | Takashi Kokubun <takashikkbn@gmail.com> | 2023-03-11 21:10:44 -0800 |
---|---|---|
committer | Takashi Kokubun <takashikkbn@gmail.com> | 2023-03-11 21:26:40 -0800 |
commit | 58f7e8b7f83babeefb39d1a919d43de237c36c8a (patch) | |
tree | ba59a593ad5f7fc16aa25261d2d8471d77162c06 | |
parent | 47a6cfca720729d1ae3af534521cbe2a2f93cd50 (diff) | |
download | ruby-58f7e8b7f83babeefb39d1a919d43de237c36c8a.tar.gz |
RJIT: Automate function pointer imports
-rw-r--r-- | lib/ruby_vm/rjit/exit_compiler.rb | 2 | ||||
-rw-r--r-- | lib/ruby_vm/rjit/insn_compiler.rb | 4 | ||||
-rw-r--r-- | rjit_c.c | 14 | ||||
-rw-r--r-- | rjit_c.rb | 338 | ||||
-rwxr-xr-x | tool/rjit/bindgen.rb | 50 |
5 files changed, 213 insertions, 195 deletions
diff --git a/lib/ruby_vm/rjit/exit_compiler.rb b/lib/ruby_vm/rjit/exit_compiler.rb index 35ebf2ddc4..59df9b564c 100644 --- a/lib/ruby_vm/rjit/exit_compiler.rb +++ b/lib/ruby_vm/rjit/exit_compiler.rb @@ -43,7 +43,7 @@ module RubyVM::RJIT asm.comment('full cfunc return') asm.mov(C_ARGS[0], EC) asm.mov(C_ARGS[1], :rax) - asm.call(C.rb_full_cfunc_return) + asm.call(C.rjit_full_cfunc_return) # TODO: count the exit diff --git a/lib/ruby_vm/rjit/insn_compiler.rb b/lib/ruby_vm/rjit/insn_compiler.rb index 761dd8f527..86983bdc3f 100644 --- a/lib/ruby_vm/rjit/insn_compiler.rb +++ b/lib/ruby_vm/rjit/insn_compiler.rb @@ -2713,7 +2713,7 @@ module RubyVM::RJIT asm.comment('call rb_str_eql_internal') asm.mov(C_ARGS[0], a_opnd) asm.mov(C_ARGS[1], b_opnd) - asm.call(gen_eq ? C.rb_str_eql_internal : C.rb_str_neq_internal) + asm.call(gen_eq ? C.rb_str_eql_internal : C.rjit_str_neq_internal) # Push the output on the stack ctx.stack_pop(2) @@ -3552,7 +3552,7 @@ module RubyVM::RJIT asm.lea(C_ARGS[3], [:rax, -argc * C.VALUE.size]) # stack_argument_pointer. NOTE: C_ARGS[3] is rcx asm.mov(C_ARGS[4], kw_splat) asm.mov(C_ARGS[5], C.VM_BLOCK_HANDLER_NONE) - asm.call(C.rb_optimized_call) + asm.call(C.rjit_optimized_call) ctx.stack_pop(argc + 1) @@ -288,8 +288,20 @@ rjit_for_each_iseq(rb_execution_context_t *ec, VALUE self, VALUE block) return Qnil; } -extern bool rb_simple_iseq_p(const rb_iseq_t *iseq); +// bindgen funcs extern ID rb_get_symbol_id(VALUE name); +extern VALUE rb_fix_aref(VALUE fix, VALUE idx); +extern VALUE rb_str_getbyte(VALUE str, VALUE index); +extern VALUE rb_vm_concat_array(VALUE ary1, VALUE ary2st); +extern VALUE rb_vm_get_ev_const(rb_execution_context_t *ec, VALUE orig_klass, ID id, VALUE allow_nil); +extern VALUE rb_vm_getclassvariable(const rb_iseq_t *iseq, const rb_control_frame_t *cfp, ID id, ICVARC ic); +extern VALUE rb_vm_opt_newarray_min(rb_execution_context_t *ec, rb_num_t num, const VALUE *ptr); +extern VALUE rb_vm_splat_array(VALUE flag, VALUE array); +extern bool rb_simple_iseq_p(const rb_iseq_t *iseq); +extern bool rb_vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_type, VALUE obj, VALUE v); +extern bool rb_vm_ic_hit_p(IC ic, const VALUE *reg_ep); +extern rb_event_flag_t rb_rjit_global_events; +extern void rb_vm_setinstancevariable(const rb_iseq_t *iseq, VALUE obj, ID id, VALUE val, IVC ic); #include "rjit_c.rbinc" @@ -126,101 +126,14 @@ module RubyVM::RJIT # :nodoc: all Primitive.cexpr! 'RBOOL(FL_TEST(obj, (VALUE)NUM2SIZET(flags)))' end - def rb_hash_aref - Primitive.cexpr! 'SIZET2NUM((size_t)rb_hash_aref)' - end - - def rb_vm_setinstancevariable - Primitive.cstmt! %{ - extern void rb_vm_setinstancevariable(const rb_iseq_t *iseq, VALUE obj, ID id, VALUE val, IVC ic); - return SIZET2NUM((size_t)rb_vm_setinstancevariable); - } - end - - def rb_full_cfunc_return - Primitive.cstmt! %{ - extern void rjit_full_cfunc_return(rb_execution_context_t *ec, VALUE return_value); - return SIZET2NUM((size_t)rjit_full_cfunc_return); - } - end - - def rb_ary_entry_internal - Primitive.cexpr! 'SIZET2NUM((size_t)rb_ary_entry_internal)' - end - - def rb_fix_mod_fix - Primitive.cexpr! 'SIZET2NUM((size_t)rb_fix_mod_fix)' - end - def rjit_for_each_iseq(&block) Primitive.rjit_for_each_iseq(block) end - def rb_rjit_global_events - Primitive.cstmt! %{ - extern rb_event_flag_t rb_rjit_global_events; - return SIZET2NUM((size_t)rb_rjit_global_events); - } - end - - def rb_str_eql_internal - Primitive.cexpr! 'SIZET2NUM((size_t)rb_str_eql_internal)' - end - - def rb_str_neq_internal - Primitive.cstmt! %{ - extern VALUE rjit_str_neq_internal(VALUE str1, VALUE str2); - return SIZET2NUM((size_t)rjit_str_neq_internal); - } - end - - def rb_ary_resurrect - Primitive.cexpr! 'SIZET2NUM((size_t)rb_ary_resurrect)' - end - - def rb_ary_store - Primitive.cexpr! 'SIZET2NUM((size_t)rb_ary_store)' - end - - def rb_hash_aset - Primitive.cexpr! 'SIZET2NUM((size_t)rb_hash_aset)' - end - def get_symbol_id(name) Primitive.cexpr! 'SIZET2NUM((size_t)rb_get_symbol_id(name))' end - def rb_get_symbol_id - Primitive.cexpr! 'SIZET2NUM((size_t)rb_get_symbol_id)' - end - - def rb_ec_ary_new_from_values - Primitive.cexpr! 'SIZET2NUM((size_t)rb_ec_ary_new_from_values)' - end - - def rb_vm_splat_array - Primitive.cstmt! %{ - extern VALUE rb_vm_splat_array(VALUE flag, VALUE array); - return SIZET2NUM((size_t)rb_vm_splat_array); - } - end - - def rb_ec_str_resurrect - Primitive.cexpr! 'SIZET2NUM((size_t)rb_ec_str_resurrect)' - end - - def rb_hash_new_with_size - Primitive.cexpr! 'SIZET2NUM((size_t)rb_hash_new_with_size)' - end - - def rb_hash_new - Primitive.cexpr! 'SIZET2NUM((size_t)rb_hash_new)' - end - - def rb_hash_bulk_insert - Primitive.cexpr! 'SIZET2NUM((size_t)rb_hash_bulk_insert)' - end - def rb_vm_frame_method_entry(cfp) _cfp = cfp.to_i cme_addr = Primitive.cexpr! 'SIZET2NUM((size_t)rb_vm_frame_method_entry((const rb_control_frame_t *)NUM2SIZET(_cfp)))' @@ -240,17 +153,6 @@ module RubyVM::RJIT # :nodoc: all Primitive.cexpr! 'rb_obj_is_kind_of(obj, c)' end - def rb_obj_is_kind_of - Primitive.cexpr! 'SIZET2NUM((size_t)rb_obj_is_kind_of)' - end - - def rb_vm_defined - Primitive.cstmt! %{ - extern bool rb_vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_type, VALUE obj, VALUE v); - return SIZET2NUM((size_t)rb_vm_defined); - } - end - def imemo_type_p(ptr, type) _ptr = ptr.to_i Primitive.cexpr! 'RBOOL(imemo_type_p((VALUE)NUM2SIZET(_ptr), NUM2UINT(type)))' @@ -272,17 +174,6 @@ module RubyVM::RJIT # :nodoc: all } end - def rb_vm_opt_newarray_min - Primitive.cstmt! %{ - extern VALUE rb_vm_opt_newarray_min(rb_execution_context_t *ec, rb_num_t num, const VALUE *ptr); - return SIZET2NUM((size_t)rb_vm_opt_newarray_min); - } - end - - def rb_gc_writebarrier - Primitive.cexpr! 'SIZET2NUM((size_t)rb_gc_writebarrier)' - end - def rb_obj_frozen_p(obj) Primitive.cexpr! 'rb_obj_frozen_p(obj)' end @@ -296,25 +187,6 @@ module RubyVM::RJIT # :nodoc: all me_addr == 0 ? nil : rb_method_entry_t.new(me_addr) end - def rb_fix_mul_fix - Primitive.cexpr! 'SIZET2NUM((size_t)rb_fix_mul_fix)' - end - - def rb_fix_div_fix - Primitive.cexpr! 'SIZET2NUM((size_t)rb_fix_div_fix)' - end - - def rb_ary_push - Primitive.cexpr! 'SIZET2NUM((size_t)rb_ary_push)' - end - - def rb_fix_aref - Primitive.cstmt! %{ - extern VALUE rb_fix_aref(VALUE fix, VALUE idx); - return SIZET2NUM((size_t)rb_fix_aref); - } - end - def rb_shape_transition_shape_capa(shape, new_capacity) _shape = shape.to_i shape_addr = Primitive.cexpr! 'SIZET2NUM((size_t)rb_shape_transition_shape_capa((rb_shape_t *)NUM2SIZET(_shape), NUM2UINT(new_capacity)))' @@ -332,69 +204,14 @@ module RubyVM::RJIT # :nodoc: all Primitive.cexpr! 'SIZET2NUM((size_t)rb_shape_id((rb_shape_t *)NUM2SIZET(_shape)))' end - def rb_ensure_iv_list_size - Primitive.cexpr! 'SIZET2NUM((size_t)rb_ensure_iv_list_size)' - end - - def rb_ivar_get - Primitive.cexpr! 'SIZET2NUM((size_t)rb_ivar_get)' - end - - def rb_vm_getclassvariable - Primitive.cstmt! %{ - extern VALUE rb_vm_getclassvariable(const rb_iseq_t *iseq, const rb_control_frame_t *cfp, ID id, ICVARC ic); - return SIZET2NUM((size_t)rb_vm_getclassvariable); - } - end - - def rb_vm_ic_hit_p - Primitive.cstmt! %{ - extern bool rb_vm_ic_hit_p(IC ic, const VALUE *reg_ep); - return SIZET2NUM((size_t)rb_vm_ic_hit_p); - } - end - - def rb_obj_as_string_result - Primitive.cexpr! 'SIZET2NUM((size_t)rb_obj_as_string_result)' - end - - def rb_str_concat_literals - Primitive.cexpr! 'SIZET2NUM((size_t)rb_str_concat_literals)' - end - def rb_class_attached_object(klass) Primitive.cexpr! 'rb_class_attached_object(klass)' end - def rb_vm_get_ev_const - Primitive.cstmt! %{ - extern VALUE rb_vm_get_ev_const(rb_execution_context_t *ec, VALUE orig_klass, ID id, VALUE allow_nil); - return SIZET2NUM((size_t)rb_vm_get_ev_const); - } - end - - def rb_vm_concat_array - Primitive.cstmt! %{ - extern VALUE rb_vm_concat_array(VALUE ary1, VALUE ary2st); - return SIZET2NUM((size_t)rb_vm_concat_array); - } - end - - def rb_vm_bh_to_procval - Primitive.cexpr! 'SIZET2NUM((size_t)rb_vm_bh_to_procval)' - end - def rb_singleton_class(obj) Primitive.cexpr! 'rb_singleton_class(obj)' end - def rb_optimized_call - Primitive.cstmt! %{ - extern VALUE rjit_optimized_call(VALUE *recv, rb_execution_context_t *ec, int argc, VALUE *argv, int kw_splat, VALUE block_handler); - return SIZET2NUM((size_t)rjit_optimized_call); - } - end - def rb_aliased_callable_method_entry(cme) _cme = cme.to_i cme_addr = Primitive.cstmt! %{ @@ -412,13 +229,6 @@ module RubyVM::RJIT # :nodoc: all rb_proc_t.new(proc_t_addr) end - def rb_str_getbyte - Primitive.cstmt! %{ - extern VALUE rb_str_getbyte(VALUE str, VALUE index); - return SIZET2NUM((size_t)rb_str_getbyte); - } - end - def rb_shape_get_shape_by_id(shape_id) _shape_id = shape_id.to_i shape_addr = Primitive.cexpr! 'SIZET2NUM((VALUE)rb_shape_get_shape_by_id((shape_id_t)NUM2UINT(_shape_id)))' @@ -906,6 +716,154 @@ module RubyVM::RJIT # :nodoc: all Primitive.cexpr! %q{ SIZET2NUM(rb_cTrueClass) } end + def C.rb_rjit_global_events + Primitive.cexpr! %q{ SIZET2NUM(rb_rjit_global_events) } + end + + def C.rb_ary_entry_internal + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ary_entry_internal) } + end + + def C.rb_ary_push + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ary_push) } + end + + def C.rb_ary_resurrect + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ary_resurrect) } + end + + def C.rb_ary_store + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ary_store) } + end + + def C.rb_ec_ary_new_from_values + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ec_ary_new_from_values) } + end + + def C.rb_ec_str_resurrect + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ec_str_resurrect) } + end + + def C.rb_ensure_iv_list_size + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ensure_iv_list_size) } + end + + def C.rb_fix_aref + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_fix_aref) } + end + + def C.rb_fix_div_fix + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_fix_div_fix) } + end + + def C.rb_fix_mod_fix + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_fix_mod_fix) } + end + + def C.rb_fix_mul_fix + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_fix_mul_fix) } + end + + def C.rb_gc_writebarrier + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_gc_writebarrier) } + end + + def C.rb_get_symbol_id + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_get_symbol_id) } + end + + def C.rb_hash_aref + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_hash_aref) } + end + + def C.rb_hash_aset + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_hash_aset) } + end + + def C.rb_hash_bulk_insert + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_hash_bulk_insert) } + end + + def C.rb_hash_new + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_hash_new) } + end + + def C.rb_hash_new_with_size + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_hash_new_with_size) } + end + + def C.rb_ivar_get + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ivar_get) } + end + + def C.rb_obj_as_string_result + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_obj_as_string_result) } + end + + def C.rb_obj_is_kind_of + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_obj_is_kind_of) } + end + + def C.rb_str_concat_literals + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_str_concat_literals) } + end + + def C.rb_str_eql_internal + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_str_eql_internal) } + end + + def C.rb_str_getbyte + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_str_getbyte) } + end + + def C.rb_vm_bh_to_procval + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_bh_to_procval) } + end + + def C.rb_vm_concat_array + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_concat_array) } + end + + def C.rb_vm_defined + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_defined) } + end + + def C.rb_vm_get_ev_const + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_get_ev_const) } + end + + def C.rb_vm_getclassvariable + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_getclassvariable) } + end + + def C.rb_vm_ic_hit_p + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_ic_hit_p) } + end + + def C.rb_vm_opt_newarray_min + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_opt_newarray_min) } + end + + def C.rb_vm_setinstancevariable + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_setinstancevariable) } + end + + def C.rb_vm_splat_array + Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_splat_array) } + end + + def C.rjit_full_cfunc_return + Primitive.cexpr! %q{ SIZET2NUM((size_t)rjit_full_cfunc_return) } + end + + def C.rjit_optimized_call + Primitive.cexpr! %q{ SIZET2NUM((size_t)rjit_optimized_call) } + end + + def C.rjit_str_neq_internal + Primitive.cexpr! %q{ SIZET2NUM((size_t)rjit_str_neq_internal) } + end + def C.CALL_DATA @CALL_DATA ||= self.rb_call_data end diff --git a/tool/rjit/bindgen.rb b/tool/rjit/bindgen.rb index 499443af7a..abff60fdc3 100755 --- a/tool/rjit/bindgen.rb +++ b/tool/rjit/bindgen.rb @@ -107,14 +107,16 @@ class BindingGenerator # @param src_path [String] # @param values [Hash{ Symbol => Array<String> }] + # @param funcs [Array<String>] # @param types [Array<String>] # @param dynamic_types [Array<String>] #ifdef-dependent immediate types, which need Primitive.cexpr! for type detection # @param skip_fields [Hash{ Symbol => Array<String> }] Struct fields that are skipped from bindgen # @param ruby_fields [Hash{ Symbol => Array<String> }] Struct VALUE fields that are considered Ruby objects - def initialize(src_path:, values:, types:, dynamic_types:, skip_fields:, ruby_fields:) + def initialize(src_path:, values:, funcs:, types:, dynamic_types:, skip_fields:, ruby_fields:) @preamble, @postamble = split_ambles(src_path) @src = String.new @values = values.transform_values(&:sort) + @funcs = funcs.sort @types = types.sort @dynamic_types = dynamic_types.sort @skip_fields = skip_fields.transform_keys(&:to_s) @@ -135,6 +137,13 @@ class BindingGenerator end end + @funcs.each do |func| + println " def C.#{func}" + println " Primitive.cexpr! %q{ SIZET2NUM((size_t)#{func}) }" + println " end" + println + end + # TODO: Support nested declarations nodes_index = nodes.group_by(&:spelling).transform_values do |values| # Try to search a declaration with definitions @@ -447,8 +456,47 @@ generator = BindingGenerator.new( rb_cNilClass rb_cSymbol rb_cTrueClass + rb_rjit_global_events ], }, + funcs: %w[ + rb_ary_entry_internal + rb_ary_push + rb_ary_resurrect + rb_ary_store + rb_ec_ary_new_from_values + rb_ec_str_resurrect + rb_ensure_iv_list_size + rb_fix_aref + rb_fix_div_fix + rb_fix_mod_fix + rb_fix_mul_fix + rb_gc_writebarrier + rb_get_symbol_id + rb_hash_aref + rb_hash_aset + rb_hash_bulk_insert + rb_hash_new + rb_hash_new_with_size + rb_ivar_get + rb_obj_as_string_result + rb_obj_is_kind_of + rb_str_concat_literals + rb_str_eql_internal + rb_str_getbyte + rb_vm_bh_to_procval + rb_vm_concat_array + rb_vm_defined + rb_vm_get_ev_const + rb_vm_getclassvariable + rb_vm_ic_hit_p + rb_vm_opt_newarray_min + rb_vm_setinstancevariable + rb_vm_splat_array + rjit_full_cfunc_return + rjit_optimized_call + rjit_str_neq_internal + ], types: %w[ CALL_DATA IC |