summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/ruby_vm/rjit/insn_compiler.rb46
-rw-r--r--rjit_c.c1
-rw-r--r--rjit_c.rb12
-rwxr-xr-xtool/rjit/bindgen.rb3
4 files changed, 60 insertions, 2 deletions
diff --git a/lib/ruby_vm/rjit/insn_compiler.rb b/lib/ruby_vm/rjit/insn_compiler.rb
index a66b5c88ef..03b33e9971 100644
--- a/lib/ruby_vm/rjit/insn_compiler.rb
+++ b/lib/ruby_vm/rjit/insn_compiler.rb
@@ -18,7 +18,7 @@ module RubyVM::RJIT
asm.incr_counter(:rjit_insns_count)
asm.comment("Insn: #{insn.name}")
- # 80/102
+ # 81/102
case insn.name
when :nop then nop(jit, ctx, asm)
when :getlocal then getlocal(jit, ctx, asm)
@@ -784,7 +784,49 @@ module RubyVM::RJIT
KeepCompiling
end
- # toregexp
+ # @param jit [RubyVM::RJIT::JITState]
+ # @param ctx [RubyVM::RJIT::Context]
+ # @param asm [RubyVM::RJIT::Assembler]
+ def toregexp(jit, ctx, asm)
+ opt = jit.operand(0, signed: true)
+ cnt = jit.operand(1)
+
+ # Save the PC and SP because this allocates an object and could
+ # raise an exception.
+ jit_prepare_routine_call(jit, ctx, asm)
+
+ asm.lea(:rax, ctx.sp_opnd(-C.VALUE.size * cnt)) # values_ptr
+ ctx.stack_pop(cnt)
+
+ asm.mov(C_ARGS[0], 0)
+ asm.mov(C_ARGS[1], cnt)
+ asm.mov(C_ARGS[2], :rax) # values_ptr
+ asm.call(C.rb_ary_tmp_new_from_values)
+
+ # Save the array so we can clear it later
+ asm.push(C_RET)
+ asm.push(C_RET) # Alignment
+
+ asm.mov(C_ARGS[0], ary)
+ asm.mov(C_ARGS[1], opt)
+ asm.call(C.rb_reg_new_ary)
+
+ # The actual regex is in RAX now. Pop the temp array from
+ # rb_ary_tmp_new_from_values into C arg regs so we can clear it
+ asm.pop(:rcx) # Alignment
+ asm.pop(:rcx) # ary
+
+ # The value we want to push on the stack is in RAX right now
+ stack_ret = ctx.stack_push
+ asm.mov(stack_ret, C_RET)
+
+ # Clear the temp array.
+ asm.mov(C_ARGS[0], :rcx) # ary
+ asm.call(C.rb_ary_clear)
+
+ KeepCompiling
+ end
+
# intern
# @param jit [RubyVM::RJIT::JITState]
diff --git a/rjit_c.c b/rjit_c.c
index 54dcb8569d..3d4d22742e 100644
--- a/rjit_c.c
+++ b/rjit_c.c
@@ -495,6 +495,7 @@ 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);
extern VALUE rb_vm_throw(const rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t throw_state, VALUE throwobj);
+extern VALUE rb_reg_new_ary(VALUE ary, int opt);
#include "rjit_c.rbinc"
diff --git a/rjit_c.rb b/rjit_c.rb
index d2e342a24e..9454ab2c1a 100644
--- a/rjit_c.rb
+++ b/rjit_c.rb
@@ -449,6 +449,10 @@ module RubyVM::RJIT # :nodoc: all
Primitive.cexpr! %q{ SIZET2NUM(rb_rjit_global_events) }
end
+ def C.rb_ary_clear
+ Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ary_clear) }
+ end
+
def C.rb_ary_entry_internal
Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ary_entry_internal) }
end
@@ -465,6 +469,10 @@ module RubyVM::RJIT # :nodoc: all
Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ary_store) }
end
+ def C.rb_ary_tmp_new_from_values
+ Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ary_tmp_new_from_values) }
+ end
+
def C.rb_backref_get
Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_backref_get) }
end
@@ -565,6 +573,10 @@ module RubyVM::RJIT # :nodoc: all
Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_reg_match_pre) }
end
+ def C.rb_reg_new_ary
+ Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_reg_new_ary) }
+ end
+
def C.rb_reg_nth_match
Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_reg_nth_match) }
end
diff --git a/tool/rjit/bindgen.rb b/tool/rjit/bindgen.rb
index 52d338e1a9..7cc97d3e3f 100755
--- a/tool/rjit/bindgen.rb
+++ b/tool/rjit/bindgen.rb
@@ -538,6 +538,9 @@ generator = BindingGenerator.new(
rb_reg_nth_match
rb_gvar_get
rb_range_new
+ rb_ary_tmp_new_from_values
+ rb_reg_new_ary
+ rb_ary_clear
],
types: %w[
CALL_DATA