summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2022-11-27 15:15:52 -0800
committerTakashi Kokubun <takashikkbn@gmail.com>2022-11-27 21:11:33 -0800
commit6844bcc6b4cdc50def1c0d30d4e8b5045fb43443 (patch)
treee76f3b03120395c52007d1fcaec6e42ace508561
parent6d26f78f684607a39249882ea686a231f8768bd5 (diff)
downloadruby-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.h2
-rw-r--r--lib/mjit/compiler.rb24
-rw-r--r--mjit_compiler.c6
-rw-r--r--tool/mk_builtin_loader.rb18
-rw-r--r--yjit/src/cruby.rs7
-rw-r--r--yjit/src/cruby_bindings.inc.rs2
6 files changed, 27 insertions, 32 deletions
diff --git a/builtin.h b/builtin.h
index 7ad52f44f4..38ad5a1629 100644
--- a/builtin.h
+++ b/builtin.h
@@ -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,