Do not assert inside rb_protect() (https://github.com/Shopify/zjit/pull/37)
This commit is contained in:
parent
c5a93df555
commit
7dd15abed3
Notes:
git
2025-04-18 13:48:21 +00:00
@ -853,13 +853,16 @@ pub use manual_defs::*;
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod test_utils {
|
pub mod test_utils {
|
||||||
use std::ptr::null;
|
use std::{ptr::null, sync::Once};
|
||||||
|
|
||||||
use crate::{options::init_options, rb_zjit_enabled_p, state::ZJITState};
|
use crate::{options::init_options, rb_zjit_enabled_p, state::ZJITState};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub fn with_rubyvm(mut func: impl FnMut()) {
|
static RUBY_VM_INIT: Once = Once::new();
|
||||||
|
|
||||||
|
/// Boot and initialize the Ruby VM for Rust testing
|
||||||
|
fn boot_rubyvm() {
|
||||||
// Boot the VM
|
// Boot the VM
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut var: VALUE = Qnil;
|
let mut var: VALUE = Qnil;
|
||||||
@ -868,32 +871,47 @@ pub mod test_utils {
|
|||||||
crate::cruby::ids::init(); // for ID! usages in tests
|
crate::cruby::ids::init(); // for ID! usages in tests
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invoke callback through rb_protect() so exceptions don't crash the process.
|
|
||||||
// "Fun" double pointer dance to get a thin function pointer to pass through C
|
|
||||||
let mut data: &mut dyn FnMut() = &mut func;
|
|
||||||
unsafe extern "C" fn callback_wrapper(data: VALUE) -> VALUE {
|
|
||||||
// SAFETY: shorter lifetime than the data local in the caller frame
|
|
||||||
let callback: &mut &mut dyn FnMut() -> bool = unsafe { std::mem::transmute(data) };
|
|
||||||
callback();
|
|
||||||
Qnil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up globals for convenience
|
// Set up globals for convenience
|
||||||
ZJITState::init(init_options());
|
ZJITState::init(init_options());
|
||||||
|
|
||||||
// Enable zjit_* instructions
|
// Enable zjit_* instructions
|
||||||
unsafe { rb_zjit_enabled_p = true; }
|
unsafe { rb_zjit_enabled_p = true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Make sure the Ruby VM is set up and run a given callback with rb_protect()
|
||||||
|
pub fn with_rubyvm<T>(mut func: impl FnMut() -> T) -> T {
|
||||||
|
RUBY_VM_INIT.call_once(|| boot_rubyvm());
|
||||||
|
|
||||||
|
// Set up a callback wrapper to store a return value
|
||||||
|
let mut result: Option<T> = None;
|
||||||
|
let mut data: &mut dyn FnMut() = &mut || {
|
||||||
|
// Store the result externally
|
||||||
|
result.replace(func());
|
||||||
|
};
|
||||||
|
|
||||||
|
// Invoke callback through rb_protect() so exceptions don't crash the process.
|
||||||
|
// "Fun" double pointer dance to get a thin function pointer to pass through C
|
||||||
|
unsafe extern "C" fn callback_wrapper(data: VALUE) -> VALUE {
|
||||||
|
// SAFETY: shorter lifetime than the data local in the caller frame
|
||||||
|
let callback: &mut &mut dyn FnMut() = unsafe { std::mem::transmute(data) };
|
||||||
|
callback();
|
||||||
|
Qnil
|
||||||
|
}
|
||||||
|
|
||||||
let mut state: c_int = 0;
|
let mut state: c_int = 0;
|
||||||
unsafe { super::rb_protect(Some(callback_wrapper), VALUE((&mut data) as *mut _ as usize), &mut state) };
|
unsafe { super::rb_protect(Some(callback_wrapper), VALUE((&mut data) as *mut _ as usize), &mut state) };
|
||||||
// TODO(alan): there should be a way to print the exception instead of swallowing it
|
// TODO(alan): there should be a way to print the exception instead of swallowing it
|
||||||
assert_eq!(0, state, "Exceptional unwind in callback. Ruby exception?");
|
assert_eq!(0, state, "Exceptional unwind in callback. Ruby exception?");
|
||||||
|
|
||||||
|
result.expect("Callback did not set result")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compile an ISeq via `RubyVM::InstructionSequence.compile`.
|
/// Compile an ISeq via `RubyVM::InstructionSequence.compile`.
|
||||||
pub fn compile_to_iseq(program: &str) -> *const rb_iseq_t {
|
pub fn compile_to_iseq(program: &str) -> *const rb_iseq_t {
|
||||||
let wrapped_iseq = compile_to_wrapped_iseq(program);
|
with_rubyvm(|| {
|
||||||
unsafe { rb_iseqw_to_iseq(wrapped_iseq) }
|
let wrapped_iseq = compile_to_wrapped_iseq(program);
|
||||||
|
unsafe { rb_iseqw_to_iseq(wrapped_iseq) }
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn define_class(name: &str, superclass: VALUE) -> VALUE {
|
pub fn define_class(name: &str, superclass: VALUE) -> VALUE {
|
||||||
@ -903,8 +921,10 @@ pub mod test_utils {
|
|||||||
|
|
||||||
/// Evaluate a given Ruby program
|
/// Evaluate a given Ruby program
|
||||||
pub fn eval(program: &str) -> VALUE {
|
pub fn eval(program: &str) -> VALUE {
|
||||||
let wrapped_iseq = compile_to_wrapped_iseq(&unindent(program, false));
|
with_rubyvm(|| {
|
||||||
unsafe { rb_funcallv(wrapped_iseq, ID!(eval), 0, null()) }
|
let wrapped_iseq = compile_to_wrapped_iseq(&unindent(program, false));
|
||||||
|
unsafe { rb_funcallv(wrapped_iseq, ID!(eval), 0, null()) }
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the ISeq of a specified method
|
/// Get the ISeq of a specified method
|
||||||
|
388
zjit/src/hir.rs
388
zjit/src/hir.rs
@ -1067,7 +1067,7 @@ mod tests {
|
|||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn assert_method_hir(method: &str, hir: &str) {
|
fn assert_method_hir(method: &str, hir: &str) {
|
||||||
let iseq = get_method_iseq(method);
|
let iseq = crate::cruby::with_rubyvm(|| get_method_iseq(method));
|
||||||
let function = iseq_to_hir(iseq).unwrap();
|
let function = iseq_to_hir(iseq).unwrap();
|
||||||
assert_function_hir(function, hir);
|
assert_function_hir(function, hir);
|
||||||
}
|
}
|
||||||
@ -1081,274 +1081,242 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn boot_vm() {
|
fn boot_vm() {
|
||||||
crate::cruby::with_rubyvm(|| {
|
let program = "nil.itself";
|
||||||
let program = "nil.itself";
|
let iseq = compile_to_iseq(program);
|
||||||
let iseq = compile_to_iseq(program);
|
assert!(iseq_to_hir(iseq).is_ok());
|
||||||
assert!(iseq_to_hir(iseq).is_ok());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_putobject() {
|
fn test_putobject() {
|
||||||
crate::cruby::with_rubyvm(|| {
|
let program = "123";
|
||||||
let program = "123";
|
let iseq = compile_to_iseq(program);
|
||||||
let iseq = compile_to_iseq(program);
|
let function = iseq_to_hir(iseq).unwrap();
|
||||||
let function = iseq_to_hir(iseq).unwrap();
|
assert_function_hir(function, "
|
||||||
assert_function_hir(function, "
|
bb0():
|
||||||
bb0():
|
v1 = Const Value(123)
|
||||||
v1 = Const Value(123)
|
v3 = Return v1
|
||||||
v3 = Return v1
|
");
|
||||||
");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_opt_plus() {
|
fn test_opt_plus() {
|
||||||
crate::cruby::with_rubyvm(|| {
|
let program = "1+2";
|
||||||
let program = "1+2";
|
let iseq = compile_to_iseq(program);
|
||||||
let iseq = compile_to_iseq(program);
|
let function = iseq_to_hir(iseq).unwrap();
|
||||||
let function = iseq_to_hir(iseq).unwrap();
|
assert_function_hir(function, "
|
||||||
assert_function_hir(function, "
|
bb0():
|
||||||
bb0():
|
v1 = Const Value(1)
|
||||||
v1 = Const Value(1)
|
v3 = Const Value(2)
|
||||||
v3 = Const Value(2)
|
v5 = Send v1, :+, v3
|
||||||
v5 = Send v1, :+, v3
|
v7 = Return v5
|
||||||
v7 = Return v5
|
");
|
||||||
");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_setlocal_getlocal() {
|
fn test_setlocal_getlocal() {
|
||||||
crate::cruby::with_rubyvm(|| {
|
let program = "a = 1; a";
|
||||||
let program = "a = 1; a";
|
let iseq = compile_to_iseq(program);
|
||||||
let iseq = compile_to_iseq(program);
|
let function = iseq_to_hir(iseq).unwrap();
|
||||||
let function = iseq_to_hir(iseq).unwrap();
|
assert_function_hir(function, "
|
||||||
assert_function_hir(function, "
|
bb0():
|
||||||
bb0():
|
v0 = Const Value(nil)
|
||||||
v0 = Const Value(nil)
|
v2 = Const Value(1)
|
||||||
v2 = Const Value(1)
|
v6 = Return v2
|
||||||
v6 = Return v2
|
");
|
||||||
");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_merge_const() {
|
fn test_merge_const() {
|
||||||
crate::cruby::with_rubyvm(|| {
|
let program = "cond = true; if cond; 3; else; 4; end";
|
||||||
let program = "cond = true; if cond; 3; else; 4; end";
|
let iseq = compile_to_iseq(program);
|
||||||
let iseq = compile_to_iseq(program);
|
let function = iseq_to_hir(iseq).unwrap();
|
||||||
let function = iseq_to_hir(iseq).unwrap();
|
assert_function_hir(function, "
|
||||||
assert_function_hir(function, "
|
bb0():
|
||||||
bb0():
|
v0 = Const Value(nil)
|
||||||
v0 = Const Value(nil)
|
v2 = Const Value(true)
|
||||||
v2 = Const Value(true)
|
v6 = Test v2
|
||||||
v6 = Test v2
|
v7 = IfFalse v6, bb1(v2)
|
||||||
v7 = IfFalse v6, bb1(v2)
|
v9 = Const Value(3)
|
||||||
v9 = Const Value(3)
|
v11 = Return v9
|
||||||
v11 = Return v9
|
bb1(v12):
|
||||||
bb1(v12):
|
v14 = Const Value(4)
|
||||||
v14 = Const Value(4)
|
v16 = Return v14
|
||||||
v16 = Return v14
|
");
|
||||||
");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_opt_plus_fixnum() {
|
fn test_opt_plus_fixnum() {
|
||||||
crate::cruby::with_rubyvm(|| {
|
eval("
|
||||||
eval("
|
def test(a, b) = a + b
|
||||||
def test(a, b) = a + b
|
test(1, 2); test(1, 2)
|
||||||
test(1, 2); test(1, 2)
|
");
|
||||||
");
|
assert_method_hir("test", "
|
||||||
assert_method_hir("test", "
|
bb0(v0, v1):
|
||||||
bb0(v0, v1):
|
v5 = PatchPoint BOPRedefined(INTEGER_REDEFINED_OP_FLAG, BOP_PLUS)
|
||||||
v5 = PatchPoint BOPRedefined(INTEGER_REDEFINED_OP_FLAG, BOP_PLUS)
|
v6 = GuardType v0, Fixnum
|
||||||
v6 = GuardType v0, Fixnum
|
v7 = GuardType v1, Fixnum
|
||||||
v7 = GuardType v1, Fixnum
|
v8 = FixnumAdd v6, v7
|
||||||
v8 = FixnumAdd v6, v7
|
v10 = Return v8
|
||||||
v10 = Return v8
|
");
|
||||||
");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_opt_minus_fixnum() {
|
fn test_opt_minus_fixnum() {
|
||||||
crate::cruby::with_rubyvm(|| {
|
eval("
|
||||||
eval("
|
def test(a, b) = a - b
|
||||||
def test(a, b) = a - b
|
test(1, 2); test(1, 2)
|
||||||
test(1, 2); test(1, 2)
|
");
|
||||||
");
|
assert_method_hir("test", "
|
||||||
assert_method_hir("test", "
|
bb0(v0, v1):
|
||||||
bb0(v0, v1):
|
v5 = PatchPoint BOPRedefined(INTEGER_REDEFINED_OP_FLAG, BOP_MINUS)
|
||||||
v5 = PatchPoint BOPRedefined(INTEGER_REDEFINED_OP_FLAG, BOP_MINUS)
|
v6 = GuardType v0, Fixnum
|
||||||
v6 = GuardType v0, Fixnum
|
v7 = GuardType v1, Fixnum
|
||||||
v7 = GuardType v1, Fixnum
|
v8 = FixnumSub v6, v7
|
||||||
v8 = FixnumSub v6, v7
|
v10 = Return v8
|
||||||
v10 = Return v8
|
");
|
||||||
");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_opt_mult_fixnum() {
|
fn test_opt_mult_fixnum() {
|
||||||
crate::cruby::with_rubyvm(|| {
|
eval("
|
||||||
eval("
|
def test(a, b) = a * b
|
||||||
def test(a, b) = a * b
|
test(1, 2); test(1, 2)
|
||||||
test(1, 2); test(1, 2)
|
");
|
||||||
");
|
assert_method_hir("test", "
|
||||||
assert_method_hir("test", "
|
bb0(v0, v1):
|
||||||
bb0(v0, v1):
|
v5 = PatchPoint BOPRedefined(INTEGER_REDEFINED_OP_FLAG, BOP_MULT)
|
||||||
v5 = PatchPoint BOPRedefined(INTEGER_REDEFINED_OP_FLAG, BOP_MULT)
|
v6 = GuardType v0, Fixnum
|
||||||
v6 = GuardType v0, Fixnum
|
v7 = GuardType v1, Fixnum
|
||||||
v7 = GuardType v1, Fixnum
|
v8 = FixnumMult v6, v7
|
||||||
v8 = FixnumMult v6, v7
|
v10 = Return v8
|
||||||
v10 = Return v8
|
");
|
||||||
");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_opt_div_fixnum() {
|
fn test_opt_div_fixnum() {
|
||||||
crate::cruby::with_rubyvm(|| {
|
eval("
|
||||||
eval("
|
def test(a, b) = a / b
|
||||||
def test(a, b) = a / b
|
test(1, 2); test(1, 2)
|
||||||
test(1, 2); test(1, 2)
|
");
|
||||||
");
|
assert_method_hir("test", "
|
||||||
assert_method_hir("test", "
|
bb0(v0, v1):
|
||||||
bb0(v0, v1):
|
v5 = PatchPoint BOPRedefined(INTEGER_REDEFINED_OP_FLAG, BOP_DIV)
|
||||||
v5 = PatchPoint BOPRedefined(INTEGER_REDEFINED_OP_FLAG, BOP_DIV)
|
v6 = GuardType v0, Fixnum
|
||||||
v6 = GuardType v0, Fixnum
|
v7 = GuardType v1, Fixnum
|
||||||
v7 = GuardType v1, Fixnum
|
v8 = FixnumDiv v6, v7
|
||||||
v8 = FixnumDiv v6, v7
|
v10 = Return v8
|
||||||
v10 = Return v8
|
");
|
||||||
");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_opt_mod_fixnum() {
|
fn test_opt_mod_fixnum() {
|
||||||
crate::cruby::with_rubyvm(|| {
|
eval("
|
||||||
eval("
|
def test(a, b) = a % b
|
||||||
def test(a, b) = a % b
|
test(1, 2); test(1, 2)
|
||||||
test(1, 2); test(1, 2)
|
");
|
||||||
");
|
assert_method_hir("test", "
|
||||||
assert_method_hir("test", "
|
bb0(v0, v1):
|
||||||
bb0(v0, v1):
|
v5 = PatchPoint BOPRedefined(INTEGER_REDEFINED_OP_FLAG, BOP_MOD)
|
||||||
v5 = PatchPoint BOPRedefined(INTEGER_REDEFINED_OP_FLAG, BOP_MOD)
|
v6 = GuardType v0, Fixnum
|
||||||
v6 = GuardType v0, Fixnum
|
v7 = GuardType v1, Fixnum
|
||||||
v7 = GuardType v1, Fixnum
|
v8 = FixnumMod v6, v7
|
||||||
v8 = FixnumMod v6, v7
|
v10 = Return v8
|
||||||
v10 = Return v8
|
");
|
||||||
");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_opt_eq_fixnum() {
|
fn test_opt_eq_fixnum() {
|
||||||
crate::cruby::with_rubyvm(|| {
|
eval("
|
||||||
eval("
|
def test(a, b) = a == b
|
||||||
def test(a, b) = a == b
|
test(1, 2); test(1, 2)
|
||||||
test(1, 2); test(1, 2)
|
");
|
||||||
");
|
assert_method_hir("test", "
|
||||||
assert_method_hir("test", "
|
bb0(v0, v1):
|
||||||
bb0(v0, v1):
|
v5 = PatchPoint BOPRedefined(INTEGER_REDEFINED_OP_FLAG, BOP_EQ)
|
||||||
v5 = PatchPoint BOPRedefined(INTEGER_REDEFINED_OP_FLAG, BOP_EQ)
|
v6 = GuardType v0, Fixnum
|
||||||
v6 = GuardType v0, Fixnum
|
v7 = GuardType v1, Fixnum
|
||||||
v7 = GuardType v1, Fixnum
|
v8 = FixnumEq v6, v7
|
||||||
v8 = FixnumEq v6, v7
|
v10 = Return v8
|
||||||
v10 = Return v8
|
");
|
||||||
");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_opt_neq_fixnum() {
|
fn test_opt_neq_fixnum() {
|
||||||
crate::cruby::with_rubyvm(|| {
|
eval("
|
||||||
eval("
|
def test(a, b) = a != b
|
||||||
def test(a, b) = a != b
|
test(1, 2); test(1, 2)
|
||||||
test(1, 2); test(1, 2)
|
");
|
||||||
");
|
assert_method_hir("test", "
|
||||||
assert_method_hir("test", "
|
bb0(v0, v1):
|
||||||
bb0(v0, v1):
|
v5 = PatchPoint BOPRedefined(INTEGER_REDEFINED_OP_FLAG, BOP_NEQ)
|
||||||
v5 = PatchPoint BOPRedefined(INTEGER_REDEFINED_OP_FLAG, BOP_NEQ)
|
v6 = GuardType v0, Fixnum
|
||||||
v6 = GuardType v0, Fixnum
|
v7 = GuardType v1, Fixnum
|
||||||
v7 = GuardType v1, Fixnum
|
v8 = FixnumNeq v6, v7
|
||||||
v8 = FixnumNeq v6, v7
|
v10 = Return v8
|
||||||
v10 = Return v8
|
");
|
||||||
");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_opt_lt_fixnum() {
|
fn test_opt_lt_fixnum() {
|
||||||
crate::cruby::with_rubyvm(|| {
|
eval("
|
||||||
eval("
|
def test(a, b) = a < b
|
||||||
def test(a, b) = a < b
|
test(1, 2); test(1, 2)
|
||||||
test(1, 2); test(1, 2)
|
");
|
||||||
");
|
assert_method_hir("test", "
|
||||||
assert_method_hir("test", "
|
bb0(v0, v1):
|
||||||
bb0(v0, v1):
|
v5 = PatchPoint BOPRedefined(INTEGER_REDEFINED_OP_FLAG, BOP_LT)
|
||||||
v5 = PatchPoint BOPRedefined(INTEGER_REDEFINED_OP_FLAG, BOP_LT)
|
v6 = GuardType v0, Fixnum
|
||||||
v6 = GuardType v0, Fixnum
|
v7 = GuardType v1, Fixnum
|
||||||
v7 = GuardType v1, Fixnum
|
v8 = FixnumLt v6, v7
|
||||||
v8 = FixnumLt v6, v7
|
v10 = Return v8
|
||||||
v10 = Return v8
|
");
|
||||||
");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_opt_le_fixnum() {
|
fn test_opt_le_fixnum() {
|
||||||
crate::cruby::with_rubyvm(|| {
|
eval("
|
||||||
eval("
|
def test(a, b) = a <= b
|
||||||
def test(a, b) = a <= b
|
test(1, 2); test(1, 2)
|
||||||
test(1, 2); test(1, 2)
|
");
|
||||||
");
|
assert_method_hir("test", "
|
||||||
assert_method_hir("test", "
|
bb0(v0, v1):
|
||||||
bb0(v0, v1):
|
v5 = PatchPoint BOPRedefined(INTEGER_REDEFINED_OP_FLAG, BOP_LE)
|
||||||
v5 = PatchPoint BOPRedefined(INTEGER_REDEFINED_OP_FLAG, BOP_LE)
|
v6 = GuardType v0, Fixnum
|
||||||
v6 = GuardType v0, Fixnum
|
v7 = GuardType v1, Fixnum
|
||||||
v7 = GuardType v1, Fixnum
|
v8 = FixnumLe v6, v7
|
||||||
v8 = FixnumLe v6, v7
|
v10 = Return v8
|
||||||
v10 = Return v8
|
");
|
||||||
");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_opt_gt_fixnum() {
|
fn test_opt_gt_fixnum() {
|
||||||
crate::cruby::with_rubyvm(|| {
|
eval("
|
||||||
eval("
|
def test(a, b) = a > b
|
||||||
def test(a, b) = a > b
|
test(1, 2); test(1, 2)
|
||||||
test(1, 2); test(1, 2)
|
");
|
||||||
");
|
assert_method_hir("test", "
|
||||||
assert_method_hir("test", "
|
bb0(v0, v1):
|
||||||
bb0(v0, v1):
|
v5 = PatchPoint BOPRedefined(INTEGER_REDEFINED_OP_FLAG, BOP_GT)
|
||||||
v5 = PatchPoint BOPRedefined(INTEGER_REDEFINED_OP_FLAG, BOP_GT)
|
v6 = GuardType v0, Fixnum
|
||||||
v6 = GuardType v0, Fixnum
|
v7 = GuardType v1, Fixnum
|
||||||
v7 = GuardType v1, Fixnum
|
v8 = FixnumGt v6, v7
|
||||||
v8 = FixnumGt v6, v7
|
v10 = Return v8
|
||||||
v10 = Return v8
|
");
|
||||||
");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_opt_ge_fixnum() {
|
fn test_opt_ge_fixnum() {
|
||||||
crate::cruby::with_rubyvm(|| {
|
eval("
|
||||||
eval("
|
def test(a, b) = a >= b
|
||||||
def test(a, b) = a >= b
|
test(1, 2); test(1, 2)
|
||||||
test(1, 2); test(1, 2)
|
");
|
||||||
");
|
assert_method_hir("test", "
|
||||||
assert_method_hir("test", "
|
bb0(v0, v1):
|
||||||
bb0(v0, v1):
|
v5 = PatchPoint BOPRedefined(INTEGER_REDEFINED_OP_FLAG, BOP_GE)
|
||||||
v5 = PatchPoint BOPRedefined(INTEGER_REDEFINED_OP_FLAG, BOP_GE)
|
v6 = GuardType v0, Fixnum
|
||||||
v6 = GuardType v0, Fixnum
|
v7 = GuardType v1, Fixnum
|
||||||
v7 = GuardType v1, Fixnum
|
v8 = FixnumGe v6, v7
|
||||||
v8 = FixnumGe v6, v7
|
v10 = Return v8
|
||||||
v10 = Return v8
|
");
|
||||||
");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user