summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2023-08-10 20:08:29 -0700
committerGitHub <noreply@github.com>2023-08-10 23:08:29 -0400
commit654b64822395ead530ac3ecae318197be85c8b52 (patch)
treeb579540aeb587b889fb202024a91c56f6e6815d3
parentb7453b91dc1e5adc9d5ebe15c644cf5e0a54e3ac (diff)
YJIT: Implement checkmatch instruction (#8203)
Notes
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
-rw-r--r--vm_insnhelper.c6
-rw-r--r--yjit/bindgen/src/main.rs1
-rw-r--r--yjit/src/codegen.rs28
-rw-r--r--yjit/src/cruby_bindings.inc.rs4
4 files changed, 39 insertions, 0 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 5cbd47d78b..7ee8fd2cbf 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -5233,6 +5233,12 @@ vm_check_match(rb_execution_context_t *ec, VALUE target, VALUE pattern, rb_num_t
}
}
+VALUE
+rb_vm_check_match(rb_execution_context_t *ec, VALUE target, VALUE pattern, rb_num_t flag)
+{
+ return vm_check_match(ec, target, pattern, flag);
+}
+
static VALUE
vm_check_keyword(lindex_t bits, lindex_t idx, const VALUE *ep)
{
diff --git a/yjit/bindgen/src/main.rs b/yjit/bindgen/src/main.rs
index 8a187bf674..6b6337d541 100644
--- a/yjit/bindgen/src/main.rs
+++ b/yjit/bindgen/src/main.rs
@@ -292,6 +292,7 @@ fn main() {
.allowlist_type("rb_builtin_attr")
.allowlist_type("ruby_tag_type")
.allowlist_type("ruby_vm_throw_flags")
+ .allowlist_type("vm_check_match_type")
// From yjit.c
.allowlist_function("rb_iseq_(get|set)_yjit_payload")
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs
index b3139253ad..1baa5edd64 100644
--- a/yjit/src/codegen.rs
+++ b/yjit/src/codegen.rs
@@ -1901,6 +1901,33 @@ fn gen_putstring(
Some(KeepCompiling)
}
+fn gen_checkmatch(
+ jit: &mut JITState,
+ asm: &mut Assembler,
+ _ocb: &mut OutlinedCb,
+) -> Option<CodegenStatus> {
+ let flag = jit.get_arg(0).as_u32();
+
+ // rb_vm_check_match is not leaf unless flag is VM_CHECKMATCH_TYPE_WHEN.
+ // See also: leafness_of_checkmatch() and check_match()
+ if flag != VM_CHECKMATCH_TYPE_WHEN {
+ jit_prepare_routine_call(jit, asm);
+ }
+
+ let pattern = asm.stack_pop(1);
+ let target = asm.stack_pop(1);
+
+ extern "C" {
+ fn rb_vm_check_match(ec: EcPtr, target: VALUE, pattern: VALUE, num: u32) -> VALUE;
+ }
+ let result = asm.ccall(rb_vm_check_match as *const u8, vec![EC, target, pattern, flag.into()]);
+
+ let stack_ret = asm.stack_push(Type::Unknown);
+ asm.mov(stack_ret, result);
+
+ Some(KeepCompiling)
+}
+
// Push Qtrue or Qfalse depending on whether the given keyword was supplied by
// the caller
fn gen_checkkeyword(
@@ -8300,6 +8327,7 @@ fn get_gen_fn(opcode: VALUE) -> Option<InsnGenFn> {
YARVINSN_expandarray => Some(gen_expandarray),
YARVINSN_defined => Some(gen_defined),
YARVINSN_definedivar => Some(gen_definedivar),
+ YARVINSN_checkmatch => Some(gen_checkmatch),
YARVINSN_checkkeyword => Some(gen_checkkeyword),
YARVINSN_concatstrings => Some(gen_concatstrings),
YARVINSN_getinstancevariable => Some(gen_getinstancevariable),
diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs
index 73dad6d2fb..1d0704073d 100644
--- a/yjit/src/cruby_bindings.inc.rs
+++ b/yjit/src/cruby_bindings.inc.rs
@@ -768,6 +768,10 @@ impl rb_proc_t {
__bindgen_bitfield_unit
}
}
+pub const VM_CHECKMATCH_TYPE_WHEN: vm_check_match_type = 1;
+pub const VM_CHECKMATCH_TYPE_CASE: vm_check_match_type = 2;
+pub const VM_CHECKMATCH_TYPE_RESCUE: vm_check_match_type = 3;
+pub type vm_check_match_type = u32;
pub const VM_SPECIAL_OBJECT_VMCORE: vm_special_object_type = 1;
pub const VM_SPECIAL_OBJECT_CBASE: vm_special_object_type = 2;
pub const VM_SPECIAL_OBJECT_CONST_BASE: vm_special_object_type = 3;