Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Instruction::Resume
  • Loading branch information
youknowone committed Jul 11, 2025
commit 0b229713106a9e28f65728be5f8e2240ff928df5
62 changes: 62 additions & 0 deletions compiler/codegen/src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1561,6 +1561,14 @@ impl Compiler<'_> {
.constants
.insert_full(ConstantData::None);

// Emit RESUME instruction at function start
emit!(
self,
Instruction::Resume {
arg: bytecode::ResumeType::AtFuncStart as u32
}
);

self.compile_statements(body)?;

// Emit None at end:
Expand Down Expand Up @@ -1976,6 +1984,12 @@ impl Compiler<'_> {
emit!(self, Instruction::GetAwaitable);
self.emit_load_const(ConstantData::None);
emit!(self, Instruction::YieldFrom);
emit!(
self,
Instruction::Resume {
arg: bytecode::ResumeType::AfterAwait as u32
}
);
emit!(self, Instruction::SetupAsyncWith { end: final_block });
} else {
emit!(self, Instruction::SetupWith { end: final_block });
Expand Down Expand Up @@ -2017,6 +2031,12 @@ impl Compiler<'_> {
emit!(self, Instruction::GetAwaitable);
self.emit_load_const(ConstantData::None);
emit!(self, Instruction::YieldFrom);
emit!(
self,
Instruction::Resume {
arg: bytecode::ResumeType::AfterAwait as u32
}
);
}

emit!(self, Instruction::WithCleanupFinish);
Expand Down Expand Up @@ -2055,6 +2075,12 @@ impl Compiler<'_> {
emit!(self, Instruction::GetANext);
self.emit_load_const(ConstantData::None);
emit!(self, Instruction::YieldFrom);
emit!(
self,
Instruction::Resume {
arg: bytecode::ResumeType::AfterAwait as u32
}
);
self.compile_store(target)?;
emit!(self, Instruction::PopBlock);
} else {
Expand Down Expand Up @@ -3526,6 +3552,12 @@ impl Compiler<'_> {
Option::None => self.emit_load_const(ConstantData::None),
};
emit!(self, Instruction::YieldValue);
emit!(
self,
Instruction::Resume {
arg: bytecode::ResumeType::AfterYield as u32
}
);
}
Expr::Await(ExprAwait { value, .. }) => {
if self.ctx.func != FunctionContext::AsyncFunction {
Expand All @@ -3535,6 +3567,12 @@ impl Compiler<'_> {
emit!(self, Instruction::GetAwaitable);
self.emit_load_const(ConstantData::None);
emit!(self, Instruction::YieldFrom);
emit!(
self,
Instruction::Resume {
arg: bytecode::ResumeType::AfterAwait as u32
}
);
}
Expr::YieldFrom(ExprYieldFrom { value, .. }) => {
match self.ctx.func {
Expand All @@ -3551,6 +3589,12 @@ impl Compiler<'_> {
emit!(self, Instruction::GetIter);
self.emit_load_const(ConstantData::None);
emit!(self, Instruction::YieldFrom);
emit!(
self,
Instruction::Resume {
arg: bytecode::ResumeType::AfterYieldFrom as u32
}
);
}
Expr::Name(ExprName { id, .. }) => self.load_name(id.as_str())?,
Expr::Lambda(ExprLambda {
Expand Down Expand Up @@ -3677,6 +3721,12 @@ impl Compiler<'_> {
compiler.compile_comprehension_element(elt)?;
compiler.mark_generator();
emit!(compiler, Instruction::YieldValue);
emit!(
compiler,
Instruction::Resume {
arg: bytecode::ResumeType::AfterYield as u32
}
);
emit!(compiler, Instruction::Pop);

Ok(())
Expand Down Expand Up @@ -4072,6 +4122,12 @@ impl Compiler<'_> {
emit!(self, Instruction::GetANext);
self.emit_load_const(ConstantData::None);
emit!(self, Instruction::YieldFrom);
emit!(
self,
Instruction::Resume {
arg: bytecode::ResumeType::AfterAwait as u32
}
);
self.compile_store(&generator.target)?;
emit!(self, Instruction::PopBlock);
} else {
Expand Down Expand Up @@ -4150,6 +4206,12 @@ impl Compiler<'_> {
emit!(self, Instruction::GetAwaitable);
self.emit_load_const(ConstantData::None);
emit!(self, Instruction::YieldFrom);
emit!(
self,
Instruction::Resume {
arg: bytecode::ResumeType::AfterAwait as u32
}
);
}

Ok(())
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions compiler/core/src/bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ pub enum ConversionFlag {
Repr = b'r' as i8,
}

/// Resume type for the RESUME instruction
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
#[repr(u32)]
pub enum ResumeType {
AtFuncStart = 0,
AfterYield = 1,
AfterYieldFrom = 2,
AfterAwait = 3,
}

pub trait Constant: Sized {
type Name: AsRef<str>;

Expand Down Expand Up @@ -549,6 +559,12 @@ pub enum Instruction {
},
YieldValue,
YieldFrom,

/// Resume execution (e.g., at function start, after yield, etc.)
Resume {
arg: Arg<u32>,
},

SetupAnnotation,
SetupLoop,

Expand Down Expand Up @@ -1304,6 +1320,7 @@ impl Instruction {
}
ReturnValue => -1,
ReturnConst { .. } => 0,
Resume { .. } => 0,
YieldValue => 0,
YieldFrom => -1,
SetupAnnotation | SetupLoop | SetupFinally { .. } | EnterFinally | EndFinally => 0,
Expand Down Expand Up @@ -1491,6 +1508,7 @@ impl Instruction {
ForIter { target } => w!(ForIter, target),
ReturnValue => w!(ReturnValue),
ReturnConst { idx } => fmt_const("ReturnConst", arg, f, idx),
Resume { arg } => w!(Resume, arg),
YieldValue => w!(YieldValue),
YieldFrom => w!(YieldFrom),
SetupAnnotation => w!(SetupAnnotation),
Expand Down
4 changes: 4 additions & 0 deletions jit/src/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,10 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
self.stack.pop();
Ok(())
}
Instruction::Resume { arg: _resume_arg } => {
// TODO: Implement the resume instruction
Ok(())
}
_ => Err(JitCompileError::NotSupported),
}
}
Expand Down
12 changes: 12 additions & 0 deletions vm/src/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -889,6 +889,18 @@ impl ExecutingFrame<'_> {
Ok(Some(ExecutionResult::Yield(value)))
}
bytecode::Instruction::YieldFrom => self.execute_yield_from(vm),
bytecode::Instruction::Resume { arg: resume_arg } => {
// Resume execution after yield, await, or at function start
// In CPython, this checks instrumentation and eval breaker
// For now, we just check for signals/interrupts
let _resume_type = resume_arg.get(arg);

// Check for interrupts if not resuming from yield_from
// if resume_type < bytecode::ResumeType::AfterYieldFrom as u32 {
// vm.check_signals()?;
// }
Ok(None)
}
Comment on lines +896 to +903
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Complete the Resume instruction implementation or document the temporary nature.

The current implementation is essentially a no-op with critical signal checking logic commented out. This could lead to missing important interrupt handling during resume operations.

Issues identified:

  1. Unused variable: _resume_type is extracted but never used
  2. Commented-out logic: The signal checking is disabled "to debug the issue"
  3. Incomplete functionality: The instruction doesn't perform its intended purpose

Consider these approaches:

Option 1: Implement proper signal checking

 bytecode::Instruction::Resume { arg: resume_arg } => {
     // Resume execution after yield, await, or at function start
-    // In CPython, this checks instrumentation and eval breaker
-    // For now, we just check for signals/interrupts
-    let _resume_type = resume_arg.get(arg);
+    let resume_type = resume_arg.get(arg);
 
-    // Temporarily disable signal checking to debug the issue
-    // Check for interrupts if not resuming from yield_from
-    // if resume_type < bytecode::ResumeType::AfterYieldFrom as u32 {
-    //     vm.check_signals()?;
-    // }
+    // Check for interrupts if not resuming from yield_from
+    if resume_type < bytecode::ResumeType::AfterYieldFrom as u32 {
+        vm.check_signals()?;
+    }
     Ok(None)
 }

Option 2: Document the temporary nature

 bytecode::Instruction::Resume { arg: resume_arg } => {
+    // TODO: Temporary no-op implementation while debugging signal issues
+    // This instruction should check for interrupts and handle instrumentation
     // Resume execution after yield, await, or at function start
-    // In CPython, this checks instrumentation and eval breaker
-    // For now, we just check for signals/interrupts
     let _resume_type = resume_arg.get(arg);
 
-    // Temporarily disable signal checking to debug the issue
     // Check for interrupts if not resuming from yield_from
     // if resume_type < bytecode::ResumeType::AfterYieldFrom as u32 {
     //     vm.check_signals()?;
     // }
     Ok(None)
 }

What specific issue is being debugged that requires disabling signal checking? This context would help determine the appropriate approach.


🏁 Script executed:

#!/bin/bash
# Search for ResumeType definition and usages
rg "ResumeType" -n .

# Search for check_signals method to see its typical usage
rg "fn check_signals" -n .

# Search for other occurrences of vm.check_signals to understand context
rg "check_signals" -n vm

Length of output: 2053


Implement signal checking in the Resume handler or document its temporary no-op

The new Instruction::Resume arm in vm/src/frame.rs currently ignores its resume_type and has all interrupt checks commented out. This placeholder will silently skip important vm.check_signals() calls and leave an unused variable.

Issues to address:

  • _resume_type is never used.
  • Critical vm.check_signals()? logic is disabled.
  • No indication of why signal checking is temporarily removed or when it’ll be restored.

Please update one of the following:

• Option A – Restore proper signal checks:

 vm/src/frame.rs
@@ -896,13 +896,15 @@ impl Frame {
             bytecode::Instruction::Resume { arg: resume_arg } => {
-                let _resume_type = resume_arg.get(arg);
+                let resume_type = resume_arg.get(arg);
 
-                // Temporarily disable signal checking to debug the issue
-                // Check for interrupts if not resuming from yield_from
-                // if resume_type < bytecode::ResumeType::AfterYieldFrom as u32 {
-                //     vm.check_signals()?;
-                // }
+                // Check for interrupts unless we’re resuming from a yield_from
+                if resume_type < bytecode::ResumeType::AfterYieldFrom as u32 {
+                    vm.check_signals()?;
+                }
                 Ok(None)
             }

• Option B – Clearly mark as temporary:

 vm/src/frame.rs
@@ -896,6 +896,10 @@ impl Frame {
             bytecode::Instruction::Resume { arg: resume_arg } => {
+                // TODO: temporary no-op while debugging signal issues.
+                // This handler must later:
+                //   1) perform instrumentation/eval breaker checks
+                //   2) re-enable vm.check_signals()
                 let _resume_type = resume_arg.get(arg);
                 Ok(None)
             }

Also, please clarify “what specific issue is being debugged” that required disabling check_signals(), and when you plan to restore full behavior.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
bytecode::Instruction::Resume { arg: resume_arg } => {
// Resume execution after yield, await, or at function start
// In CPython, this checks instrumentation and eval breaker
// For now, we just check for signals/interrupts
let _resume_type = resume_arg.get(arg);
// Temporarily disable signal checking to debug the issue
// Check for interrupts if not resuming from yield_from
// if resume_type < bytecode::ResumeType::AfterYieldFrom as u32 {
// vm.check_signals()?;
// }
Ok(None)
}
bytecode::Instruction::Resume { arg: resume_arg } => {
// Resume execution after yield, await, or at function start
// In CPython, this checks instrumentation and eval breaker
// For now, we just check for signals/interrupts
let resume_type = resume_arg.get(arg);
// Check for interrupts unless we’re resuming from a yield_from
if resume_type < bytecode::ResumeType::AfterYieldFrom as u32 {
vm.check_signals()?;
}
Ok(None)
}
🤖 Prompt for AI Agents
In vm/src/frame.rs around lines 896 to 908, the Resume instruction handler
currently disables signal checking and leaves the resume_type variable unused,
which can cause missed interrupt handling and unclear code intent. To fix this,
either restore the vm.check_signals()? call with the appropriate condition on
resume_type to ensure signals are checked as intended, or if signal checking is
temporarily disabled for debugging, add a clear comment explaining the specific
issue being debugged, why check_signals() is disabled, and when full signal
checking will be restored. Also, remove the unused _resume_type variable if not
used or rename it to _ to avoid warnings.

bytecode::Instruction::SetupAnnotation => self.setup_annotations(vm),
bytecode::Instruction::SetupLoop => {
self.push_block(BlockType::Loop);
Expand Down
Loading