summaryrefslogtreecommitdiff
path: root/zjit
diff options
context:
space:
mode:
authorMax Bernstein <ruby@bernsteinbear.com>2026-03-25 09:59:07 -0400
committerMax Bernstein <tekknolagi@gmail.com>2026-03-25 14:02:09 -0400
commitbe783db2c2bb73456f808291aa4f72fa02861641 (patch)
tree6565ccfa17b5a69ab12d9dddc6a53d498ba7bfdd /zjit
parent17cd9bffd37710dbcd746a62b3d49ea7213095ed (diff)
ZJIT: Support negative indices in more places
Diffstat (limited to 'zjit')
-rw-r--r--zjit/src/cruby_methods.rs3
-rw-r--r--zjit/src/hir/opt_tests.rs47
2 files changed, 29 insertions, 21 deletions
diff --git a/zjit/src/cruby_methods.rs b/zjit/src/cruby_methods.rs
index bd4310e084..767f6499e8 100644
--- a/zjit/src/cruby_methods.rs
+++ b/zjit/src/cruby_methods.rs
@@ -379,6 +379,7 @@ fn inline_array_aset(fun: &mut hir::Function, block: hir::BlockId, recv: hir::In
let index = fun.push_insn(block, hir::Insn::UnboxFixnum { val: index });
let length = fun.push_insn(block, hir::Insn::ArrayLength { array: recv });
let index = fun.push_insn(block, hir::Insn::GuardLess { left: index, right: length, state });
+ let index = fun.push_insn(block, hir::Insn::AdjustBounds { index, length });
let zero = fun.push_insn(block, hir::Insn::Const { val: hir::Const::CInt64(0) });
use crate::hir::SideExitReason;
let index = fun.push_insn(block, hir::Insn::GuardGreaterEq { left: index, right: zero, reason: SideExitReason::GuardGreaterEq, state });
@@ -476,6 +477,7 @@ fn inline_string_getbyte(fun: &mut hir::Function, block: hir::BlockId, recv: hir
//
// This is unlike most other guards.
let unboxed_index = fun.push_insn(block, hir::Insn::GuardLess { left: unboxed_index, right: len, state });
+ let unboxed_index = fun.push_insn(block, hir::Insn::AdjustBounds { index: unboxed_index, length: len });
let zero = fun.push_insn(block, hir::Insn::Const { val: hir::Const::CInt64(0) });
use crate::hir::SideExitReason;
let _ = fun.push_insn(block, hir::Insn::GuardGreaterEq { left: unboxed_index, right: zero, reason: SideExitReason::GuardGreaterEq, state });
@@ -499,6 +501,7 @@ fn inline_string_setbyte(fun: &mut hir::Function, block: hir::BlockId, recv: hir
return_type: types::CInt64,
});
let unboxed_index = fun.push_insn(block, hir::Insn::GuardLess { left: unboxed_index, right: len, state });
+ let unboxed_index = fun.push_insn(block, hir::Insn::AdjustBounds { index: unboxed_index, length: len });
let zero = fun.push_insn(block, hir::Insn::Const { val: hir::Const::CInt64(0) });
use crate::hir::SideExitReason;
let _ = fun.push_insn(block, hir::Insn::GuardGreaterEq { left: unboxed_index, right: zero, reason: SideExitReason::GuardGreaterEq, state });
diff --git a/zjit/src/hir/opt_tests.rs b/zjit/src/hir/opt_tests.rs
index db3889449f..af438c361b 100644
--- a/zjit/src/hir/opt_tests.rs
+++ b/zjit/src/hir/opt_tests.rs
@@ -9062,9 +9062,9 @@ mod hir_opt_tests {
v34:CUInt64 = LoadField v33, :_rbasic_flags@0x1040
v35:CUInt64 = GuardNoBitsSet v34, RUBY_FL_FREEZE=CUInt64(2048)
v37:CUInt64 = GuardNoBitsSet v34, RUBY_ELTS_SHARED=CUInt64(4096)
- v45:CInt64[1] = Const CInt64(1)
+ v46:CInt64[1] = Const CInt64(1)
v39:CInt64 = ArrayLength v33
- v40:CInt64[1] = GuardLess v45, v39
+ v40:CInt64[1] = GuardLess v46, v39
ArrayAset v33, v40, v19
WriteBarrier v33, v19
CheckInterrupts
@@ -9108,9 +9108,10 @@ mod hir_opt_tests {
v43:CInt64 = UnboxFixnum v38
v44:CInt64 = ArrayLength v37
v45:CInt64 = GuardLess v43, v44
- v46:CInt64[0] = Const CInt64(0)
- v47:CInt64 = GuardGreaterEq v45, v46
- ArrayAset v37, v47, v16
+ v46:CInt64 = AdjustBounds v45, v44
+ v47:CInt64[0] = Const CInt64(0)
+ v48:CInt64 = GuardGreaterEq v46, v47
+ ArrayAset v37, v48, v16
WriteBarrier v37, v16
CheckInterrupts
Return v16
@@ -9533,11 +9534,12 @@ mod hir_opt_tests {
v30:CInt64 = UnboxFixnum v29
v31:CInt64 = LoadField v28, :len@0x1040
v32:CInt64 = GuardLess v30, v31
- v33:CInt64[0] = Const CInt64(0)
- v34:CInt64 = GuardGreaterEq v32, v33
- v35:Fixnum = StringGetbyte v28, v32
+ v33:CInt64 = AdjustBounds v32, v31
+ v34:CInt64[0] = Const CInt64(0)
+ v35:CInt64 = GuardGreaterEq v33, v34
+ v36:Fixnum = StringGetbyte v28, v33
CheckInterrupts
- Return v35
+ Return v36
");
}
@@ -9573,8 +9575,9 @@ mod hir_opt_tests {
v34:CInt64 = UnboxFixnum v33
v35:CInt64 = LoadField v32, :len@0x1040
v36:CInt64 = GuardLess v34, v35
- v37:CInt64[0] = Const CInt64(0)
- v38:CInt64 = GuardGreaterEq v36, v37
+ v37:CInt64 = AdjustBounds v36, v35
+ v38:CInt64[0] = Const CInt64(0)
+ v39:CInt64 = GuardGreaterEq v37, v38
v23:Fixnum[5] = Const Value(5)
CheckInterrupts
Return v23
@@ -9615,11 +9618,12 @@ mod hir_opt_tests {
v35:CInt64 = UnboxFixnum v33
v36:CInt64 = LoadField v32, :len@0x1040
v37:CInt64 = GuardLess v35, v36
- v38:CInt64[0] = Const CInt64(0)
- v39:CInt64 = GuardGreaterEq v37, v38
- v40:CUInt64 = LoadField v32, :_rbasic_flags@0x1041
- v41:CUInt64 = GuardNoBitsSet v40, RUBY_FL_FREEZE=CUInt64(2048)
- v42:Fixnum = StringSetbyteFixnum v32, v33, v34
+ v38:CInt64 = AdjustBounds v37, v36
+ v39:CInt64[0] = Const CInt64(0)
+ v40:CInt64 = GuardGreaterEq v38, v39
+ v41:CUInt64 = LoadField v32, :_rbasic_flags@0x1041
+ v42:CUInt64 = GuardNoBitsSet v41, RUBY_FL_FREEZE=CUInt64(2048)
+ v43:Fixnum = StringSetbyteFixnum v32, v33, v34
CheckInterrupts
Return v34
");
@@ -9661,11 +9665,12 @@ mod hir_opt_tests {
v35:CInt64 = UnboxFixnum v33
v36:CInt64 = LoadField v32, :len@0x1040
v37:CInt64 = GuardLess v35, v36
- v38:CInt64[0] = Const CInt64(0)
- v39:CInt64 = GuardGreaterEq v37, v38
- v40:CUInt64 = LoadField v32, :_rbasic_flags@0x1041
- v41:CUInt64 = GuardNoBitsSet v40, RUBY_FL_FREEZE=CUInt64(2048)
- v42:Fixnum = StringSetbyteFixnum v32, v33, v34
+ v38:CInt64 = AdjustBounds v37, v36
+ v39:CInt64[0] = Const CInt64(0)
+ v40:CInt64 = GuardGreaterEq v38, v39
+ v41:CUInt64 = LoadField v32, :_rbasic_flags@0x1041
+ v42:CUInt64 = GuardNoBitsSet v41, RUBY_FL_FREEZE=CUInt64(2048)
+ v43:Fixnum = StringSetbyteFixnum v32, v33, v34
CheckInterrupts
Return v34
");