RJIT: Automate function pointer imports

This commit is contained in:
Takashi Kokubun 2023-03-11 21:10:44 -08:00
parent 47a6cfca72
commit 58f7e8b7f8
5 changed files with 213 additions and 195 deletions

View File

@ -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

View File

@ -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)

View File

@ -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"

338
rjit_c.rb
View File

@ -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

View File

@ -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