Oparg resume depth (#7515)

* Base resume context

* Fixes for api change

* Align codegen

* Align `frame.rs` to the api changes

* fix jit

* Use new oparg

* Fix doc

* let `ir` to decide exception depth
This commit is contained in:
Shahar Naveh
2026-03-27 13:47:52 +01:00
committed by GitHub
parent e3ac1bf8dc
commit 410721740d
7 changed files with 168 additions and 111 deletions

View File

@@ -1277,7 +1277,7 @@ impl Compiler {
context: OpArgMarker::marker(),
}
.into(),
arg: OpArg::new(u32::from(bytecode::ResumeType::AtFuncStart)),
arg: OpArg::new(oparg::ResumeLocation::AtFuncStart.into()),
target: BlockIdx::NULL,
location,
end_location,
@@ -7200,9 +7200,9 @@ impl Compiler {
self,
Instruction::Resume {
context: if is_await {
bytecode::ResumeType::AfterAwait
oparg::ResumeContext::from(oparg::ResumeLocation::AfterAwait)
} else {
bytecode::ResumeType::AfterYieldFrom
oparg::ResumeContext::from(oparg::ResumeLocation::AfterYieldFrom)
}
}
);
@@ -7374,7 +7374,7 @@ impl Compiler {
emit!(
self,
Instruction::Resume {
context: bytecode::ResumeType::AfterYield
context: oparg::ResumeContext::from(oparg::ResumeLocation::AfterYield)
}
);
}
@@ -7596,7 +7596,9 @@ impl Compiler {
emit!(
compiler,
Instruction::Resume {
context: bytecode::ResumeType::AfterYield
context: oparg::ResumeContext::from(
oparg::ResumeLocation::AfterYield
)
}
);
emit!(compiler, Instruction::PopTop);

View File

@@ -363,7 +363,7 @@ impl CodeInfo {
}
}
let mut block_to_offset = vec![Label::new(0); blocks.len()];
let mut block_to_offset = vec![Label::from_u32(0); blocks.len()];
// block_to_index: maps block idx to instruction index (for exception table)
// This is the index into the final instructions array, including EXTENDED_ARG and CACHE
let mut block_to_index = vec![0u32; blocks.len()];
@@ -372,7 +372,7 @@ impl CodeInfo {
loop {
let mut num_instructions = 0;
for (idx, block) in iter_blocks(&blocks) {
block_to_offset[idx.idx()] = Label::new(num_instructions as u32);
block_to_offset[idx.idx()] = Label::from_u32(num_instructions as u32);
// block_to_index uses the same value as block_to_offset but as u32
// because lasti in frame.rs is the index into instructions array
// and instructions array index == byte offset (each instruction is 1 CodeUnit)
@@ -2188,20 +2188,19 @@ pub(crate) fn label_exception_targets(blocks: &mut [Block]) {
}
// Set RESUME DEPTH1 flag based on last yield's except depth
if matches!(
blocks[bi].instructions[i].instr.real(),
Some(Instruction::Resume { .. })
) {
const RESUME_AT_FUNC_START: u32 = 0;
const RESUME_OPARG_LOCATION_MASK: u32 = 0x3;
const RESUME_OPARG_DEPTH1_MASK: u32 = 0x4;
if (u32::from(arg) & RESUME_OPARG_LOCATION_MASK) != RESUME_AT_FUNC_START {
if last_yield_except_depth == 1 {
blocks[bi].instructions[i].arg =
OpArg::new(u32::from(arg) | RESUME_OPARG_DEPTH1_MASK);
if let Some(Instruction::Resume { context }) =
blocks[bi].instructions[i].instr.real()
{
let location = context.get(arg).location();
match location {
oparg::ResumeLocation::AtFuncStart => {}
_ => {
if last_yield_except_depth == 1 {
blocks[bi].instructions[i].arg =
OpArg::new(oparg::ResumeContext::new(location, true).as_u32());
}
last_yield_except_depth = -1;
}
last_yield_except_depth = -1;
}
}

View File

@@ -27,7 +27,7 @@ pub use crate::bytecode::{
BinaryOperator, BuildSliceArgCount, CommonConstant, ComparisonOperator, ConvertValueOparg,
IntrinsicFunction1, IntrinsicFunction2, Invert, Label, LoadAttr, LoadSuperAttr,
MakeFunctionFlag, MakeFunctionFlags, NameIdx, OpArg, OpArgByte, OpArgState, OpArgType,
RaiseKind, ResumeType, SpecialMethod, UnpackExArgs,
RaiseKind, SpecialMethod, UnpackExArgs,
},
};
@@ -1041,7 +1041,7 @@ impl<C: Constant> CodeObject<C> {
}
// arrow and offset
let arrow = if label_targets.contains(&Label::new(offset as u32)) {
let arrow = if label_targets.contains(&Label::from_u32(offset as u32)) {
">>"
} else {
" "

View File

@@ -304,7 +304,7 @@ pub enum Instruction {
} = 120,
// CPython 3.14 RESUME (128)
Resume {
context: Arg<oparg::ResumeType>,
context: Arg<oparg::ResumeContext>,
} = 128,
// CPython 3.14 specialized opcodes (129-211)
BinaryOpAddFloat = 129, // Placeholder

View File

@@ -276,48 +276,6 @@ impl fmt::Display for ConvertValueOparg {
}
}
/// Resume type for the RESUME instruction
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum ResumeType {
AtFuncStart,
AfterYield,
AfterYieldFrom,
AfterAwait,
Other(u32),
}
impl From<u32> for ResumeType {
fn from(value: u32) -> Self {
match value {
0 => Self::AtFuncStart,
5 => Self::AfterYield,
2 => Self::AfterYieldFrom,
3 => Self::AfterAwait,
_ => Self::Other(value),
}
}
}
impl From<ResumeType> for u32 {
fn from(typ: ResumeType) -> Self {
match typ {
ResumeType::AtFuncStart => 0,
ResumeType::AfterYield => 5,
ResumeType::AfterYieldFrom => 2,
ResumeType::AfterAwait => 3,
ResumeType::Other(v) => v,
}
}
}
impl core::fmt::Display for ResumeType {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
u32::from(*self).fmt(f)
}
}
impl OpArgType for ResumeType {}
pub type NameIdx = u32;
impl OpArgType for u32 {}
@@ -756,14 +714,8 @@ macro_rules! newtype_oparg {
impl $name {
/// Creates a new [`$name`] instance.
#[must_use]
pub const fn new(value: u32) -> Self {
Self(value)
}
/// Alias to [`$name::new`].
#[must_use]
pub const fn from_u32(value: u32) -> Self {
Self::new(value)
Self(value)
}
/// Returns the oparg as a `u32` value.
@@ -843,15 +795,119 @@ newtype_oparg!(
pub struct Label(u32)
);
newtype_oparg!(
/// Context for [`Instruction::Resume`].
///
/// The oparg consists of two parts:
/// 1. [`ResumeContext::location`]: Indicates where the instruction occurs.
/// 2. [`ResumeContext::is_exception_depth1`]: Is the instruction is at except-depth 1.
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct ResumeContext(u32)
);
impl ResumeContext {
/// [CPython `RESUME_OPARG_LOCATION_MASK`](https://github.com/python/cpython/blob/v3.14.3/Include/internal/pycore_opcode_utils.h#L84)
pub const LOCATION_MASK: u32 = 0x3;
/// [CPython `RESUME_OPARG_DEPTH1_MASK`](https://github.com/python/cpython/blob/v3.14.3/Include/internal/pycore_opcode_utils.h#L85)
pub const DEPTH1_MASK: u32 = 0x4;
#[must_use]
pub const fn new(location: ResumeLocation, is_exception_depth1: bool) -> Self {
let value = if is_exception_depth1 {
Self::DEPTH1_MASK
} else {
0
};
Self::from_u32(location.as_u32() | value)
}
/// Resume location is determined by [`Self::LOCATION_MASK`].
#[must_use]
pub fn location(&self) -> ResumeLocation {
// SAFETY: The mask should return a value that is in range.
unsafe { ResumeLocation::try_from(self.as_u32() & Self::LOCATION_MASK).unwrap_unchecked() }
}
/// True if the bit at [`Self::DEPTH1_MASK`] is on.
#[must_use]
pub const fn is_exception_depth1(&self) -> bool {
(self.as_u32() & Self::DEPTH1_MASK) != 0
}
}
#[derive(Copy, Clone)]
pub enum ResumeLocation {
/// At the start of a function, which is neither a generator, coroutine nor an async generator.
AtFuncStart,
/// After a `yield` expression.
AfterYield,
/// After a `yield from` expression.
AfterYieldFrom,
/// After an `await` expression.
AfterAwait,
}
impl From<ResumeLocation> for ResumeContext {
fn from(location: ResumeLocation) -> Self {
Self::new(location, false)
}
}
impl TryFrom<u32> for ResumeLocation {
type Error = MarshalError;
fn try_from(value: u32) -> Result<Self, Self::Error> {
Ok(match value {
0 => Self::AtFuncStart,
1 => Self::AfterYield,
2 => Self::AfterYieldFrom,
3 => Self::AfterAwait,
_ => return Err(Self::Error::InvalidBytecode),
})
}
}
impl ResumeLocation {
#[must_use]
pub const fn as_u8(&self) -> u8 {
match self {
Self::AtFuncStart => 0,
Self::AfterYield => 1,
Self::AfterYieldFrom => 2,
Self::AfterAwait => 3,
}
}
#[must_use]
pub const fn as_u32(&self) -> u32 {
self.as_u8() as u32
}
}
impl From<ResumeLocation> for u8 {
fn from(location: ResumeLocation) -> Self {
location.as_u8()
}
}
impl From<ResumeLocation> for u32 {
fn from(location: ResumeLocation) -> Self {
location.as_u32()
}
}
impl VarNums {
#[must_use]
pub const fn idx_1(self) -> VarNum {
VarNum::new(self.0 >> 4)
VarNum::from_u32(self.0 >> 4)
}
#[must_use]
pub const fn idx_2(self) -> VarNum {
VarNum::new(self.0 & 15)
VarNum::from_u32(self.0 & 15)
}
#[must_use]
@@ -887,7 +943,7 @@ impl LoadAttrBuilder {
#[must_use]
pub const fn build(self) -> LoadAttr {
let value = (self.name_idx << 1) | (self.is_method as u32);
LoadAttr::new(value)
LoadAttr::from_u32(value)
}
#[must_use]
@@ -937,7 +993,7 @@ impl LoadSuperAttrBuilder {
pub const fn build(self) -> LoadSuperAttr {
let value =
(self.name_idx << 2) | ((self.has_class as u32) << 1) | (self.is_load_method as u32);
LoadSuperAttr::new(value)
LoadSuperAttr::from_u32(value)
}
#[must_use]

View File

@@ -162,7 +162,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
let target = after
.checked_add(u32::from(arg))
.ok_or(JitCompileError::BadBytecode)?;
Ok(Label::new(target))
Ok(Label::from_u32(target))
}
fn jump_target_backward(
@@ -177,7 +177,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
let target = after
.checked_sub(u32::from(arg))
.ok_or(JitCompileError::BadBytecode)?;
Ok(Label::new(target))
Ok(Label::from_u32(target))
}
fn instruction_target(
@@ -232,7 +232,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
let mut in_unreachable_code = false;
for (offset, &raw_instr) in clean_instructions.iter().enumerate() {
let label = Label::new(offset as u32);
let label = Label::from_u32(offset as u32);
let (instruction, arg) = arg_state.get(raw_instr);
// If this is a label that some earlier jump can target,

View File

@@ -2437,7 +2437,7 @@ impl ExecutingFrame<'_> {
}
Instruction::ForIter { .. } => {
// Relative forward jump: target = lasti + caches + delta
let target = bytecode::Label::new(self.lasti() + 1 + u32::from(arg));
let target = bytecode::Label::from_u32(self.lasti() + 1 + u32::from(arg));
self.adaptive(|s, ii, cb| s.specialize_for_iter(vm, u32::from(arg), ii, cb));
self.execute_for_iter(vm, target)?;
Ok(None)
@@ -3571,7 +3571,7 @@ impl ExecutingFrame<'_> {
Instruction::Send { .. } => {
// (receiver, v -- receiver, retval)
self.adaptive(|s, ii, cb| s.specialize_send(vm, ii, cb));
let exit_label = bytecode::Label::new(self.lasti() + 1 + u32::from(arg));
let exit_label = bytecode::Label::from_u32(self.lasti() + 1 + u32::from(arg));
let receiver = self.nth_value(1);
let can_fast_send = !self.specialization_eval_frame_active(vm)
&& (receiver.downcast_ref_if_exact::<PyGenerator>(vm).is_some()
@@ -3609,7 +3609,7 @@ impl ExecutingFrame<'_> {
}
}
Instruction::SendGen => {
let exit_label = bytecode::Label::new(self.lasti() + 1 + u32::from(arg));
let exit_label = bytecode::Label::from_u32(self.lasti() + 1 + u32::from(arg));
// Stack: [receiver, val] — peek receiver before popping
let receiver = self.nth_value(1);
let can_fast_send = !self.specialization_eval_frame_active(vm)
@@ -3740,7 +3740,7 @@ impl ExecutingFrame<'_> {
}
// Specialized LOAD_ATTR opcodes
Instruction::LoadAttrMethodNoDict => {
let oparg = LoadAttr::new(u32::from(arg));
let oparg = LoadAttr::from_u32(u32::from(arg));
let cache_base = self.lasti() as usize;
let owner = self.top_value();
@@ -3759,7 +3759,7 @@ impl ExecutingFrame<'_> {
}
}
Instruction::LoadAttrMethodLazyDict => {
let oparg = LoadAttr::new(u32::from(arg));
let oparg = LoadAttr::from_u32(u32::from(arg));
let cache_base = self.lasti() as usize;
let owner = self.top_value();
@@ -3779,7 +3779,7 @@ impl ExecutingFrame<'_> {
}
}
Instruction::LoadAttrMethodWithValues => {
let oparg = LoadAttr::new(u32::from(arg));
let oparg = LoadAttr::from_u32(u32::from(arg));
let cache_base = self.lasti() as usize;
let attr_name = self.code.names[oparg.name_idx() as usize];
@@ -3814,7 +3814,7 @@ impl ExecutingFrame<'_> {
self.load_attr_slow(vm, oparg)
}
Instruction::LoadAttrInstanceValue => {
let oparg = LoadAttr::new(u32::from(arg));
let oparg = LoadAttr::from_u32(u32::from(arg));
let cache_base = self.lasti() as usize;
let attr_name = self.code.names[oparg.name_idx() as usize];
@@ -3836,7 +3836,7 @@ impl ExecutingFrame<'_> {
self.load_attr_slow(vm, oparg)
}
Instruction::LoadAttrWithHint => {
let oparg = LoadAttr::new(u32::from(arg));
let oparg = LoadAttr::from_u32(u32::from(arg));
let cache_base = self.lasti() as usize;
let attr_name = self.code.names[oparg.name_idx() as usize];
@@ -3861,7 +3861,7 @@ impl ExecutingFrame<'_> {
self.load_attr_slow(vm, oparg)
}
Instruction::LoadAttrModule => {
let oparg = LoadAttr::new(u32::from(arg));
let oparg = LoadAttr::from_u32(u32::from(arg));
let cache_base = self.lasti() as usize;
let attr_name = self.code.names[oparg.name_idx() as usize];
@@ -3885,7 +3885,7 @@ impl ExecutingFrame<'_> {
self.load_attr_slow(vm, oparg)
}
Instruction::LoadAttrNondescriptorNoDict => {
let oparg = LoadAttr::new(u32::from(arg));
let oparg = LoadAttr::from_u32(u32::from(arg));
let cache_base = self.lasti() as usize;
let owner = self.top_value();
@@ -3907,7 +3907,7 @@ impl ExecutingFrame<'_> {
self.load_attr_slow(vm, oparg)
}
Instruction::LoadAttrNondescriptorWithValues => {
let oparg = LoadAttr::new(u32::from(arg));
let oparg = LoadAttr::from_u32(u32::from(arg));
let cache_base = self.lasti() as usize;
let attr_name = self.code.names[oparg.name_idx() as usize];
@@ -3945,7 +3945,7 @@ impl ExecutingFrame<'_> {
self.load_attr_slow(vm, oparg)
}
Instruction::LoadAttrClass => {
let oparg = LoadAttr::new(u32::from(arg));
let oparg = LoadAttr::from_u32(u32::from(arg));
let cache_base = self.lasti() as usize;
let owner = self.top_value();
@@ -3968,7 +3968,7 @@ impl ExecutingFrame<'_> {
self.load_attr_slow(vm, oparg)
}
Instruction::LoadAttrClassWithMetaclassCheck => {
let oparg = LoadAttr::new(u32::from(arg));
let oparg = LoadAttr::from_u32(u32::from(arg));
let cache_base = self.lasti() as usize;
let owner = self.top_value();
@@ -3994,7 +3994,7 @@ impl ExecutingFrame<'_> {
self.load_attr_slow(vm, oparg)
}
Instruction::LoadAttrGetattributeOverridden => {
let oparg = LoadAttr::new(u32::from(arg));
let oparg = LoadAttr::from_u32(u32::from(arg));
let cache_base = self.lasti() as usize;
let owner = self.top_value();
let type_version = self.code.instructions.read_cache_u32(cache_base + 1);
@@ -4021,7 +4021,7 @@ impl ExecutingFrame<'_> {
self.load_attr_slow(vm, oparg)
}
Instruction::LoadAttrSlot => {
let oparg = LoadAttr::new(u32::from(arg));
let oparg = LoadAttr::from_u32(u32::from(arg));
let cache_base = self.lasti() as usize;
let owner = self.top_value();
@@ -4045,7 +4045,7 @@ impl ExecutingFrame<'_> {
self.load_attr_slow(vm, oparg)
}
Instruction::LoadAttrProperty => {
let oparg = LoadAttr::new(u32::from(arg));
let oparg = LoadAttr::from_u32(u32::from(arg));
let cache_base = self.lasti() as usize;
let owner = self.top_value();
@@ -5247,7 +5247,7 @@ impl ExecutingFrame<'_> {
return Ok(None);
}
}
let oparg = LoadSuperAttr::new(oparg);
let oparg = LoadSuperAttr::from_u32(oparg);
self.load_super_attr(vm, oparg)
}
Instruction::LoadSuperAttrMethod => {
@@ -5314,7 +5314,7 @@ impl ExecutingFrame<'_> {
return Ok(None);
}
}
let oparg = LoadSuperAttr::new(oparg);
let oparg = LoadSuperAttr::from_u32(oparg);
self.load_super_attr(vm, oparg)
}
Instruction::CompareOpInt => {
@@ -5581,7 +5581,7 @@ impl ExecutingFrame<'_> {
self.unpack_sequence(size as u32, vm)
}
Instruction::ForIterRange => {
let target = bytecode::Label::new(self.lasti() + 1 + u32::from(arg));
let target = bytecode::Label::from_u32(self.lasti() + 1 + u32::from(arg));
let iter = self.top_value();
if let Some(range_iter) = iter.downcast_ref_if_exact::<PyRangeIterator>(vm) {
if let Some(value) = range_iter.fast_next() {
@@ -5596,7 +5596,7 @@ impl ExecutingFrame<'_> {
}
}
Instruction::ForIterList => {
let target = bytecode::Label::new(self.lasti() + 1 + u32::from(arg));
let target = bytecode::Label::from_u32(self.lasti() + 1 + u32::from(arg));
let iter = self.top_value();
if let Some(list_iter) = iter.downcast_ref_if_exact::<PyListIterator>(vm) {
if let Some(value) = list_iter.fast_next() {
@@ -5611,7 +5611,7 @@ impl ExecutingFrame<'_> {
}
}
Instruction::ForIterTuple => {
let target = bytecode::Label::new(self.lasti() + 1 + u32::from(arg));
let target = bytecode::Label::from_u32(self.lasti() + 1 + u32::from(arg));
let iter = self.top_value();
if let Some(tuple_iter) = iter.downcast_ref_if_exact::<PyTupleIterator>(vm) {
if let Some(value) = tuple_iter.fast_next() {
@@ -5626,7 +5626,7 @@ impl ExecutingFrame<'_> {
}
}
Instruction::ForIterGen => {
let target = bytecode::Label::new(self.lasti() + 1 + u32::from(arg));
let target = bytecode::Label::from_u32(self.lasti() + 1 + u32::from(arg));
let iter = self.top_value();
if self.specialization_eval_frame_active(vm) {
self.execute_for_iter(vm, target)?;
@@ -5868,7 +5868,7 @@ impl ExecutingFrame<'_> {
Instruction::InstrumentedJumpForward => {
let src_offset = (self.lasti() - 1) * 2;
let target_idx = self.lasti() + u32::from(arg);
let target = bytecode::Label::new(target_idx);
let target = bytecode::Label::from_u32(target_idx);
self.jump(target);
if self.monitoring_mask & monitoring::EVENT_JUMP != 0 {
monitoring::fire_jump(vm, self.code, src_offset, target.as_u32() * 2)?;
@@ -5878,7 +5878,7 @@ impl ExecutingFrame<'_> {
Instruction::InstrumentedJumpBackward => {
let src_offset = (self.lasti() - 1) * 2;
let target_idx = self.lasti() + 1 - u32::from(arg);
let target = bytecode::Label::new(target_idx);
let target = bytecode::Label::from_u32(target_idx);
self.jump(target);
if self.monitoring_mask & monitoring::EVENT_JUMP != 0 {
monitoring::fire_jump(vm, self.code, src_offset, target.as_u32() * 2)?;
@@ -5887,7 +5887,7 @@ impl ExecutingFrame<'_> {
}
Instruction::InstrumentedForIter => {
let src_offset = (self.lasti() - 1) * 2;
let target = bytecode::Label::new(self.lasti() + 1 + u32::from(arg));
let target = bytecode::Label::from_u32(self.lasti() + 1 + u32::from(arg));
let continued = self.execute_for_iter(vm, target)?;
if continued {
if self.monitoring_mask & monitoring::EVENT_BRANCH_LEFT != 0 {
@@ -5937,7 +5937,7 @@ impl ExecutingFrame<'_> {
let obj = self.pop_value();
let value = obj.try_to_bool(vm)?;
if value {
self.jump(bytecode::Label::new(target_idx));
self.jump(bytecode::Label::from_u32(target_idx));
if self.monitoring_mask & monitoring::EVENT_BRANCH_RIGHT != 0 {
monitoring::fire_branch_right(vm, self.code, src_offset, target_idx * 2)?;
}
@@ -5950,7 +5950,7 @@ impl ExecutingFrame<'_> {
let obj = self.pop_value();
let value = obj.try_to_bool(vm)?;
if !value {
self.jump(bytecode::Label::new(target_idx));
self.jump(bytecode::Label::from_u32(target_idx));
if self.monitoring_mask & monitoring::EVENT_BRANCH_RIGHT != 0 {
monitoring::fire_branch_right(vm, self.code, src_offset, target_idx * 2)?;
}
@@ -5962,7 +5962,7 @@ impl ExecutingFrame<'_> {
let target_idx = self.lasti() + 1 + u32::from(arg);
let value = self.pop_value();
if vm.is_none(&value) {
self.jump(bytecode::Label::new(target_idx));
self.jump(bytecode::Label::from_u32(target_idx));
if self.monitoring_mask & monitoring::EVENT_BRANCH_RIGHT != 0 {
monitoring::fire_branch_right(vm, self.code, src_offset, target_idx * 2)?;
}
@@ -5974,7 +5974,7 @@ impl ExecutingFrame<'_> {
let target_idx = self.lasti() + 1 + u32::from(arg);
let value = self.pop_value();
if !vm.is_none(&value) {
self.jump(bytecode::Label::new(target_idx));
self.jump(bytecode::Label::from_u32(target_idx));
if self.monitoring_mask & monitoring::EVENT_BRANCH_RIGHT != 0 {
monitoring::fire_branch_right(vm, self.code, src_offset, target_idx * 2)?;
}
@@ -6366,7 +6366,7 @@ impl ExecutingFrame<'_> {
self.push_value(exception.into());
// 4. Jump to handler
self.jump(bytecode::Label::new(entry.target));
self.jump(bytecode::Label::from_u32(entry.target));
Ok(None)
} else {
@@ -6971,7 +6971,7 @@ impl ExecutingFrame<'_> {
bytecode::Instruction::EndFor | bytecode::Instruction::InstrumentedEndFor
)
{
return bytecode::Label::new(target.as_u32() + 1);
return bytecode::Label::from_u32(target.as_u32() + 1);
}
target
}
@@ -8952,7 +8952,7 @@ impl ExecutingFrame<'_> {
unit.op,
bytecode::Instruction::EndFor | bytecode::Instruction::InstrumentedEndFor
) {
bytecode::Label::new(target.as_u32() + 1)
bytecode::Label::from_u32(target.as_u32() + 1)
} else {
target
}