aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2023-03-11 21:10:44 -0800
committerTakashi Kokubun <takashikkbn@gmail.com>2023-03-11 21:26:40 -0800
commit58f7e8b7f83babeefb39d1a919d43de237c36c8a (patch)
treeba59a593ad5f7fc16aa25261d2d8471d77162c06
parent47a6cfca720729d1ae3af534521cbe2a2f93cd50 (diff)
downloadruby-58f7e8b7f83babeefb39d1a919d43de237c36c8a.tar.gz
RJIT: Automate function pointer imports
-rw-r--r--lib/ruby_vm/rjit/exit_compiler.rb2
-rw-r--r--lib/ruby_vm/rjit/insn_compiler.rb4
-rw-r--r--rjit_c.c14
-rw-r--r--rjit_c.rb338
-rwxr-xr-xtool/rjit/bindgen.rb50
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)
diff --git a/rjit_c.c b/rjit_c.c
index 90f39de883..0df65d53d9 100644
--- a/rjit_c.c
+++ b/rjit_c.c
@@ -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"
diff --git a/rjit_c.rb b/rjit_c.rb
index bbf26a7597..6e4c05bc87 100644
--- a/rjit_c.rb
+++ b/rjit_c.rb
@@ -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