Skip to content

Commit 3e82da7

Browse files
authored
ZJIT: Don't mark control-flow opcodes as invalidating locals (ruby#15694)
jump, branchif, etc don't invalidate locals in the JIT; they might in the interpreter because they can execute arbitrary code, but the JIT side exits before that happens.
1 parent 8d097bc commit 3e82da7

File tree

3 files changed

+52
-50
lines changed

3 files changed

+52
-50
lines changed

zjit/src/hir.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5299,6 +5299,20 @@ impl ProfileOracle {
52995299
}
53005300
}
53015301

5302+
fn invalidates_locals(opcode: u32, operands: *const VALUE) -> bool {
5303+
match opcode {
5304+
// Control-flow is non-leaf in the interpreter because it can execute arbitrary code on
5305+
// interrupt. But in the JIT, we side-exit if there is a pending interrupt.
5306+
YARVINSN_jump
5307+
| YARVINSN_branchunless
5308+
| YARVINSN_branchif
5309+
| YARVINSN_branchnil
5310+
| YARVINSN_leave => false,
5311+
// TODO(max): Read the invokebuiltin target from operands and determine if it's leaf
5312+
_ => unsafe { !rb_zjit_insn_leaf(opcode as i32, operands) }
5313+
}
5314+
}
5315+
53025316
/// The index of the self parameter in the HIR function
53035317
pub const SELF_PARAM_IDX: usize = 0;
53045318

@@ -5434,7 +5448,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
54345448
}
54355449

54365450
// Flag a future getlocal/setlocal to add a patch point if this instruction is not leaf.
5437-
if unsafe { !rb_zjit_insn_leaf(opcode as i32, pc.offset(1)) } {
5451+
if invalidates_locals(opcode, unsafe { pc.offset(1) }) {
54385452
local_inval = true;
54395453
}
54405454

zjit/src/hir/opt_tests.rs

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9638,26 +9638,24 @@ mod hir_opt_tests {
96389638
Jump bb2(v8, v9, v10, v11, v12)
96399639
bb2(v14:BasicObject, v15:BasicObject, v16:BasicObject, v17:BasicObject, v18:NilClass):
96409640
CheckInterrupts
9641-
v27:BasicObject = GetLocal :a, l0, EP@6
9642-
SetLocal :formatted, l0, EP@3, v27
9643-
v39:BasicObject = GetLocal :formatted, l0, EP@3
9641+
SetLocal :formatted, l0, EP@3, v15
96449642
PatchPoint SingleRactorMode
9645-
v56:HeapBasicObject = GuardType v14, HeapBasicObject
9646-
v57:HeapBasicObject = GuardShape v56, 0x1000
9647-
StoreField v57, :@formatted@0x1001, v39
9648-
WriteBarrier v57, v39
9649-
v60:CShape[0x1002] = Const CShape(0x1002)
9650-
StoreField v57, :_shape_id@0x1003, v60
9651-
v45:Class[VMFrozenCore] = Const Value(VALUE(0x1008))
9643+
v54:HeapBasicObject = GuardType v14, HeapBasicObject
9644+
v55:HeapBasicObject = GuardShape v54, 0x1000
9645+
StoreField v55, :@formatted@0x1001, v15
9646+
WriteBarrier v55, v15
9647+
v58:CShape[0x1002] = Const CShape(0x1002)
9648+
StoreField v55, :_shape_id@0x1003, v58
9649+
v43:Class[VMFrozenCore] = Const Value(VALUE(0x1008))
96529650
PatchPoint MethodRedefined(Class@0x1010, lambda@0x1018, cme:0x1020)
96539651
PatchPoint NoSingletonClass(Class@0x1010)
9654-
v65:BasicObject = CCallWithFrame v45, :RubyVM::FrozenCore.lambda@0x1048, block=0x1050
9655-
v48:BasicObject = GetLocal :a, l0, EP@6
9656-
v49:BasicObject = GetLocal :_b, l0, EP@5
9657-
v50:BasicObject = GetLocal :_c, l0, EP@4
9658-
v51:BasicObject = GetLocal :formatted, l0, EP@3
9652+
v63:BasicObject = CCallWithFrame v43, :RubyVM::FrozenCore.lambda@0x1048, block=0x1050
9653+
v46:BasicObject = GetLocal :a, l0, EP@6
9654+
v47:BasicObject = GetLocal :_b, l0, EP@5
9655+
v48:BasicObject = GetLocal :_c, l0, EP@4
9656+
v49:BasicObject = GetLocal :formatted, l0, EP@3
96599657
CheckInterrupts
9660-
Return v65
9658+
Return v63
96619659
");
96629660
}
96639661

zjit/src/hir/tests.rs

Lines changed: 23 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,17 +1069,14 @@ pub mod hir_build_tests {
10691069
v18:CBool = Test v11
10701070
IfFalse v18, bb3(v10, v11, v12)
10711071
v22:Fixnum[3] = Const Value(3)
1072-
PatchPoint NoEPEscape(test)
10731072
CheckInterrupts
10741073
Jump bb4(v10, v11, v22)
1075-
bb3(v29:BasicObject, v30:BasicObject, v31:NilClass):
1076-
v35:Fixnum[4] = Const Value(4)
1077-
PatchPoint NoEPEscape(test)
1078-
Jump bb4(v29, v30, v35)
1079-
bb4(v40:BasicObject, v41:BasicObject, v42:Fixnum):
1080-
PatchPoint NoEPEscape(test)
1074+
bb3(v27:BasicObject, v28:BasicObject, v29:NilClass):
1075+
v33:Fixnum[4] = Const Value(4)
1076+
Jump bb4(v27, v28, v33)
1077+
bb4(v36:BasicObject, v37:BasicObject, v38:Fixnum):
10811078
CheckInterrupts
1082-
Return v42
1079+
Return v38
10831080
");
10841081
}
10851082

@@ -1366,23 +1363,20 @@ pub mod hir_build_tests {
13661363
CheckInterrupts
13671364
Jump bb4(v10, v16, v20)
13681365
bb4(v26:BasicObject, v27:BasicObject, v28:BasicObject):
1369-
PatchPoint NoEPEscape(test)
1370-
v34:Fixnum[0] = Const Value(0)
1371-
v37:BasicObject = SendWithoutBlock v28, :>, v34 # SendFallbackReason: Uncategorized(opt_gt)
1366+
v32:Fixnum[0] = Const Value(0)
1367+
v35:BasicObject = SendWithoutBlock v28, :>, v32 # SendFallbackReason: Uncategorized(opt_gt)
13721368
CheckInterrupts
1373-
v40:CBool = Test v37
1374-
IfTrue v40, bb3(v26, v27, v28)
1375-
v43:NilClass = Const Value(nil)
1376-
PatchPoint NoEPEscape(test)
1369+
v38:CBool = Test v35
1370+
IfTrue v38, bb3(v26, v27, v28)
1371+
v41:NilClass = Const Value(nil)
13771372
CheckInterrupts
13781373
Return v27
1379-
bb3(v53:BasicObject, v54:BasicObject, v55:BasicObject):
1380-
PatchPoint NoEPEscape(test)
1381-
v62:Fixnum[1] = Const Value(1)
1382-
v65:BasicObject = SendWithoutBlock v54, :+, v62 # SendFallbackReason: Uncategorized(opt_plus)
1383-
v70:Fixnum[1] = Const Value(1)
1384-
v73:BasicObject = SendWithoutBlock v55, :-, v70 # SendFallbackReason: Uncategorized(opt_minus)
1385-
Jump bb4(v53, v65, v73)
1374+
bb3(v49:BasicObject, v50:BasicObject, v51:BasicObject):
1375+
v56:Fixnum[1] = Const Value(1)
1376+
v59:BasicObject = SendWithoutBlock v50, :+, v56 # SendFallbackReason: Uncategorized(opt_plus)
1377+
v64:Fixnum[1] = Const Value(1)
1378+
v67:BasicObject = SendWithoutBlock v51, :-, v64 # SendFallbackReason: Uncategorized(opt_minus)
1379+
Jump bb4(v49, v59, v67)
13861380
");
13871381
}
13881382

@@ -3064,15 +3058,13 @@ pub mod hir_build_tests {
30643058
CheckInterrupts
30653059
v35:CBool[true] = Test v32
30663060
IfFalse v35, bb3(v16, v17, v18, v19, v20, v25)
3067-
PatchPoint NoEPEscape(open)
3068-
v42:BasicObject = InvokeBlock, v25 # SendFallbackReason: Uncategorized(invokeblock)
3069-
v45:BasicObject = InvokeBuiltin dir_s_close, v16, v25
3061+
v40:BasicObject = InvokeBlock, v25 # SendFallbackReason: Uncategorized(invokeblock)
3062+
v43:BasicObject = InvokeBuiltin dir_s_close, v16, v25
30703063
CheckInterrupts
3071-
Return v42
3072-
bb3(v51, v52, v53, v54, v55, v56):
3073-
PatchPoint NoEPEscape(open)
3064+
Return v40
3065+
bb3(v49, v50, v51, v52, v53, v54):
30743066
CheckInterrupts
3075-
Return v56
3067+
Return v54
30763068
");
30773069
}
30783070

@@ -3548,12 +3540,10 @@ pub mod hir_build_tests {
35483540
v22:Fixnum[1] = Const Value(1)
35493541
v24:Fixnum[1] = Const Value(1)
35503542
v27:BasicObject = SendWithoutBlock v22, :+, v24 # SendFallbackReason: Uncategorized(opt_plus)
3551-
PatchPoint NoEPEscape(test)
35523543
Jump bb3(v10, v27, v12)
3553-
bb3(v32:BasicObject, v33:BasicObject, v34:BasicObject):
3554-
PatchPoint NoEPEscape(test)
3544+
bb3(v30:BasicObject, v31:BasicObject, v32:BasicObject):
35553545
CheckInterrupts
3556-
Return v33
3546+
Return v31
35573547
");
35583548
}
35593549

0 commit comments

Comments
 (0)