summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin.c15
-rw-r--r--builtin.h13
-rw-r--r--compile.c16
-rw-r--r--tool/mk_builtin_loader.rb58
-rw-r--r--vm_core.h1
5 files changed, 93 insertions, 10 deletions
diff --git a/builtin.c b/builtin.c
index d936d1ceb6..d0d998da49 100644
--- a/builtin.c
+++ b/builtin.c
@@ -25,9 +25,12 @@ rb_load_with_builtin_functions(const char *feature_name, const struct rb_builtin
const unsigned char *bin = builtin_lookup(feature_name, &size);
// load binary
- GET_VM()->builtin_function_table = table;
+ rb_vm_t *vm = GET_VM();
+ if (vm->builtin_function_table != NULL) rb_bug("vm->builtin_function_table should be NULL.");
+ vm->builtin_function_table = table;
+ vm->builtin_inline_index = 0;
const rb_iseq_t *iseq = rb_iseq_ibf_load_bytes((const char *)bin, size);
- GET_VM()->builtin_function_table = NULL;
+ vm->builtin_function_table = NULL;
// exec
rb_iseq_eval(iseq);
@@ -38,3 +41,11 @@ Init_builtin(void)
{
//
}
+
+// inline
+VALUE
+rb_vm_lvar_exposed(rb_execution_context_t *ec, int index)
+{
+ const rb_control_frame_t *cfp = ec->cfp;
+ return cfp->ep[index];
+}
diff --git a/builtin.h b/builtin.h
index ee99e21dcc..236dfd961c 100644
--- a/builtin.h
+++ b/builtin.h
@@ -43,6 +43,19 @@ static inline void rb_builtin_function_check_arity13(VALUE (*f)(rb_execution_con
static inline void rb_builtin_function_check_arity14(VALUE (*f)(rb_execution_context_t *ec, VALUE self, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)){}
static inline void rb_builtin_function_check_arity15(VALUE (*f)(rb_execution_context_t *ec, VALUE self, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)){}
+VALUE rb_vm_lvar_exposed(rb_execution_context_t *ec, int index);
+
+// inline
+inline VALUE
+rb_vm_lvar(rb_execution_context_t *ec, int index)
+{
+#if VM_CORE_H_EC_DEFINED
+ return ec->cfp->ep[index];
+#else
+ return rb_vm_lvar_exposed(ec, index);
+#endif
+}
+
// dump/load
struct builtin_binary {
diff --git a/compile.c b/compile.c
index 131f82a47d..e0b850556e 100644
--- a/compile.c
+++ b/compile.c
@@ -6740,8 +6740,7 @@ iseq_builtin_function_lookup(const rb_iseq_t *iseq, const char *name)
{
int i;
const struct rb_builtin_function *table = ISEQ_COMPILE_DATA(iseq)->builtin_function_table;
- for (i=0; table[i].name != NULL; i++) {
- // fprintf(stderr, "table[%d].name:%s, name:%s\n", i, table[i].name, name);
+ for (i=0; table[i].index != -1; i++) {
if (strcmp(table[i].name, name) == 0) {
return &table[i];
}
@@ -6886,6 +6885,8 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
}
#endif
const char *builtin_func;
+ NODE *args_node = node->nd_args;
+
if (UNLIKELY(iseq_has_builtin_function_table(iseq)) &&
(builtin_func = iseq_builtin_function_name(mid)) != NULL) {
@@ -6894,9 +6895,18 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
return COMPILE_NG;
}
else {
+ char inline_func[0x20];
+ retry:;
const struct rb_builtin_function *bf = iseq_builtin_function_lookup(iseq, builtin_func);
if (bf == NULL) {
+ if (strcmp("inline!", builtin_func) == 0) {
+ int inline_index = GET_VM()->builtin_inline_index++;
+ snprintf(inline_func, 0x20, "__builtin_inline%d", inline_index);
+ builtin_func = inline_func;
+ args_node = NULL;
+ goto retry;
+ }
if (1) {
rb_bug("can't find builtin function:%s", builtin_func);
}
@@ -6908,7 +6918,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
// fprintf(stderr, "func_name:%s -> %p\n", builtin_func, bf->func_ptr);
- argc = setup_args(iseq, args, node->nd_args, &flag, &keywords);
+ argc = setup_args(iseq, args, args_node, &flag, &keywords);
if (FIX2INT(argc) != bf->argc) {
COMPILE_ERROR(ERROR_ARGS "argc is not match for builtin function:%s (expect %d but %d)",
diff --git a/tool/mk_builtin_loader.rb b/tool/mk_builtin_loader.rb
index 4f140a6f6b..8f4d5df60b 100644
--- a/tool/mk_builtin_loader.rb
+++ b/tool/mk_builtin_loader.rb
@@ -1,8 +1,21 @@
-def collect_builtin iseq_ary, bs
+def collect_builtin base, iseq_ary, bs, inlines
code = iseq_ary[13]
+ params = iseq_ary[10]
+ prev_insn = nil
+ lineno = nil
code.each{|insn|
+ case insn
+ when Array
+ # ok
+ when Integer
+ lineno = insn
+ next
+ else
+ next
+ end
+
next unless Array === insn
case insn[0]
when :send
@@ -11,18 +24,31 @@ def collect_builtin iseq_ary, bs
func_name = $1
argc = ci[:orig_argc]
- if bs[func_name] && bs[func_name] != argc
- raise
+ if func_name == 'inline!'
+ raise "argc (#{argc}) of inline! should be 1" unless argc == 1
+ raise "1st argument should be string literal" unless prev_insn[0] == :putstring
+ text = prev_insn[1]
+
+ func_name = "__builtin_inline#{inlines.size}"
+ inlines << [func_name, [lineno, text, params]]
+ argc -= 1
end
+
+ if bs[func_name] &&
+ bs[func_name] != argc
+ raise "same builtin function \"#{func_name}\", but different arity (was #{bs[func_name]} but #{argc})"
+ end
+
bs[func_name] = argc
end
else
insn[1..-1].each{|op|
if op.is_a?(Array) && op[0] == "YARVInstructionSequence/SimpleDataFormat"
- collect_builtin op, bs
+ collect_builtin base, op, bs, inlines
end
}
end
+ prev_insn = insn
}
end
# ruby mk_builtin_loader.rb TARGET_FILE.rb
@@ -33,7 +59,8 @@ def mk_builtin_header file
base = File.basename(file, '.rb')
ofile = "#{base}.rbinc"
- collect_builtin(RubyVM::InstructionSequence.compile_file(file, false).to_a, bs = {})
+ # bs = { func_name => argc }
+ collect_builtin(base, RubyVM::InstructionSequence.compile_file(file, false).to_a, bs = {}, inlines = [])
open(ofile, 'w'){|f|
f.puts "// -*- c -*-"
@@ -42,6 +69,27 @@ def mk_builtin_header file
f.puts "// by #{__FILE__}"
f.puts "// with #{file}"
f.puts
+ lineno = 6
+
+ inlines.each{|name, (body_lineno, text, params)|
+ f.puts "static VALUE #{name}(rb_execution_context_t *ec, const VALUE self) {"
+ lineno += 1
+
+ params.reverse_each.with_index{|param, i|
+ next unless Symbol === param
+ f.puts "MAYBE_UNUSED(const VALUE) #{param} = rb_vm_lvar(ec, #{-3 - i});"
+ lineno += 1
+ }
+ f.puts "#line #{body_lineno} \"#{file}\""
+ lineno += 1
+
+ f.puts text
+ lineno += text.count("\n") + 1
+
+ f.puts "#line #{lineno + 2} \"#{ofile}\"" # TODO: restore line number.
+ f.puts "}"
+ lineno += 2
+ }
f.puts "static void load_#{base}(void)"
f.puts "{"
diff --git a/vm_core.h b/vm_core.h
index 9e158df923..9c5b723d6a 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -652,6 +652,7 @@ typedef struct rb_vm_struct {
st_table *frozen_strings;
const struct rb_builtin_function *builtin_function_table;
+ int builtin_inline_index;
/* params */
struct { /* size in byte */