diff options
author | Takashi Kokubun <takashikkbn@gmail.com> | 2022-11-27 15:15:52 -0800 |
---|---|---|
committer | Takashi Kokubun <takashikkbn@gmail.com> | 2022-11-27 21:11:33 -0800 |
commit | 6844bcc6b4cdc50def1c0d30d4e8b5045fb43443 (patch) | |
tree | e76f3b03120395c52007d1fcaec6e42ace508561 | |
parent | 6d26f78f684607a39249882ea686a231f8768bd5 (diff) | |
download | ruby-6844bcc6b4cdc50def1c0d30d4e8b5045fb43443.tar.gz |
MJIT: Use a String buffer in builtin compilers
instead of FILE*.
Using C.fprintf is slower than String manipulation on memory. I'm going
to change the way MJIT writes files, and this is a prerequisite for it.
-rw-r--r-- | builtin.h | 2 | ||||
-rw-r--r-- | lib/mjit/compiler.rb | 24 | ||||
-rw-r--r-- | mjit_compiler.c | 6 | ||||
-rw-r--r-- | tool/mk_builtin_loader.rb | 18 | ||||
-rw-r--r-- | yjit/src/cruby.rs | 7 | ||||
-rw-r--r-- | yjit/src/cruby_bindings.inc.rs | 2 |
6 files changed, 27 insertions, 32 deletions
@@ -13,7 +13,7 @@ struct rb_builtin_function { const char * const name; // for jit - void (*compiler)(FILE *, long, unsigned, bool); + void (*compiler)(VALUE, long, unsigned, bool); }; #define RB_BUILTIN_FUNCTION(_i, _name, _fname, _arity, _compiler) {\ diff --git a/lib/mjit/compiler.rb b/lib/mjit/compiler.rb index 1100ca94bf..07a5646542 100644 --- a/lib/mjit/compiler.rb +++ b/lib/mjit/compiler.rb @@ -203,8 +203,8 @@ module RubyVM::MJIT return src, next_pos, finish_p, compile_insns end when :invokebuiltin, :opt_invokebuiltin_delegate - if compile_invokebuiltin(f, insn, stack_size, sp_inc, body, operands) - return '', next_pos, finish_p, compile_insns + if src = compile_invokebuiltin(insn, stack_size, sp_inc, body, operands) + return src, next_pos, finish_p, compile_insns end when :opt_getconstant_path if src = compile_getconstant_path(stack_size, pos, insn_len, operands, status) @@ -215,7 +215,9 @@ module RubyVM::MJIT # opt_invokebuiltin_delegate_leave also implements leave insn. We need to handle it here for inlining. if insn.name == :opt_invokebuiltin_delegate_leave - compile_invokebuiltin(f, insn, stack_size, sp_inc, body, operands) + if invokebuiltin_src = compile_invokebuiltin(insn, stack_size, sp_inc, body, operands) + src << invokebuiltin_src + end else if stack_size != 1 $stderr.puts "MJIT warning: Unexpected JIT stack_size on leave: #{stack_size}" # TODO: check mjit_opts? @@ -407,18 +409,18 @@ module RubyVM::MJIT end end - def compile_invokebuiltin(f, insn, stack_size, sp_inc, body, operands) + def compile_invokebuiltin(insn, stack_size, sp_inc, body, operands) bf = C.RB_BUILTIN.new(operands[0]) if bf.compiler > 0 index = (insn.name == :invokebuiltin ? -1 : operands[1]) - C.fprintf(f, "{\n") - C.fprintf(f, " VALUE val;\n") - C.builtin_compiler(f, bf, index, stack_size, body.builtin_inline_p) - C.fprintf(f, " stack[#{stack_size + sp_inc - 1}] = val;\n") - C.fprintf(f, "}\n") - return true + src = +"{\n" + src << " VALUE val;\n" + C.builtin_compiler(src, bf, index, stack_size, body.builtin_inline_p) + src << " stack[#{stack_size + sp_inc - 1}] = val;\n" + src << "}\n" + return src else - return false + return nil end end diff --git a/mjit_compiler.c b/mjit_compiler.c index 6b2ff433e2..0e9f499424 100644 --- a/mjit_compiler.c +++ b/mjit_compiler.c @@ -143,11 +143,11 @@ cdhash_to_hash(rb_execution_context_t *ec, VALUE self, VALUE cdhash_addr) } static VALUE -builtin_compile(rb_execution_context_t *ec, VALUE self, VALUE f_addr, VALUE bf_addr, VALUE index, VALUE stack_size, VALUE builtin_inline_p) +builtin_compile(rb_execution_context_t *ec, VALUE self, VALUE buf, VALUE bf_addr, VALUE index, VALUE stack_size, VALUE builtin_inline_p) { - FILE *f = (FILE *)NUM2PTR(f_addr); + // Call "mjit_compile_invokebuiltin_for_#{func}" in mk_builtin_loader.rb RB_BUILTIN bf = (RB_BUILTIN)NUM2PTR(bf_addr); - bf->compiler(f, NIL_P(index) ? -1 : NUM2LONG(index), NUM2UINT(stack_size), RTEST(builtin_inline_p)); + bf->compiler(buf, NIL_P(index) ? -1 : NUM2LONG(index), NUM2UINT(stack_size), RTEST(builtin_inline_p)); return Qnil; } diff --git a/tool/mk_builtin_loader.rb b/tool/mk_builtin_loader.rb index 6b4ae121d9..c4f36889d6 100644 --- a/tool/mk_builtin_loader.rb +++ b/tool/mk_builtin_loader.rb @@ -325,10 +325,10 @@ def mk_builtin_header file . map {|i|", argv[#{i}]"} \ . join('') f.puts %'static void' - f.puts %'mjit_compile_invokebuiltin_for_#{func}(FILE *f, long index, unsigned stack_size, bool inlinable_p)' + f.puts %'mjit_compile_invokebuiltin_for_#{func}(VALUE buf, long index, unsigned stack_size, bool inlinable_p)' f.puts %'{' - f.puts %' fprintf(f, " VALUE self = GET_SELF();\\n");' - f.puts %' fprintf(f, " typedef VALUE (*func)(rb_execution_context_t *, VALUE#{decl});\\n");' + f.puts %' rb_str_catf(buf, " VALUE self = GET_SELF();\\n");' + f.puts %' rb_str_catf(buf, " typedef VALUE (*func)(rb_execution_context_t *, VALUE#{decl});\\n");' if inlines.has_key? cfunc_name body_lineno, text, locals, func_name = inlines[cfunc_name] lineno, str = generate_cexpr(ofile, lineno, line_file, body_lineno, text, locals, func_name) @@ -336,22 +336,22 @@ def mk_builtin_header file str.gsub(/^(?!#)/, ' ').each_line {|i| j = RubyVM::CEscape.rstring2cstr(i).dup j.sub!(/^ return\b/ , ' val =') - f.printf(%' fprintf(f, "%%s", %s);\n', j) + f.printf(%' rb_str_catf(buf, "%%s", %s);\n', j) } f.puts(%' return;') f.puts(%' }') end if argc > 0 f.puts %' if (index == -1) {' - f.puts %' fprintf(f, " const VALUE *argv = &stack[%d];\\n", stack_size - #{argc});' + f.puts %' rb_str_catf(buf, " const VALUE *argv = &stack[%d];\\n", stack_size - #{argc});' f.puts %' }' f.puts %' else {' - f.puts %' fprintf(f, " const unsigned int lnum = ISEQ_BODY(GET_ISEQ())->local_table_size;\\n");' - f.puts %' fprintf(f, " const VALUE *argv = GET_EP() - lnum - VM_ENV_DATA_SIZE + 1 + %ld;\\n", index);' + f.puts %' rb_str_catf(buf, " const unsigned int lnum = ISEQ_BODY(GET_ISEQ())->local_table_size;\\n");' + f.puts %' rb_str_catf(buf, " const VALUE *argv = GET_EP() - lnum - VM_ENV_DATA_SIZE + 1 + %ld;\\n", index);' f.puts %' }' end - f.puts %' fprintf(f, " func f = (func)%"PRIuVALUE"; /* == #{cfunc_name} */\\n", (VALUE)#{cfunc_name});' - f.puts %' fprintf(f, " val = f(ec, self#{argv});\\n");' + f.puts %' rb_str_catf(buf, " func f = (func)%"PRIuVALUE"; /* == #{cfunc_name} */\\n", (VALUE)#{cfunc_name});' + f.puts %' rb_str_catf(buf, " val = f(ec, self#{argv});\\n");' f.puts %'}' f.puts } diff --git a/yjit/src/cruby.rs b/yjit/src/cruby.rs index d37af38320..229cfa109e 100644 --- a/yjit/src/cruby.rs +++ b/yjit/src/cruby.rs @@ -270,13 +270,6 @@ pub struct rb_method_cfunc_t { _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>, } -/// Opaque FILE type from the C standard library -#[repr(C)] -pub struct FILE { - _data: [u8; 0], - _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>, -} - /// Opaque call-cache type from vm_callinfo.h #[repr(C)] pub struct rb_callcache { diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index 78967cd4ce..ea57bd69d8 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -1047,7 +1047,7 @@ pub struct rb_builtin_function { pub name: *const ::std::os::raw::c_char, pub compiler: ::std::option::Option< unsafe extern "C" fn( - arg1: *mut FILE, + arg1: VALUE, arg2: ::std::os::raw::c_long, arg3: ::std::os::raw::c_uint, arg4: bool, |