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
Next Next commit
set_f_lineno, set_f_lasti, PyAtomic refactor
- Implement set_f_lineno with stack analysis and deferred unwinding
- Add Frame::set_lasti() for trace callback line jumps
- Implement co_branches() on code objects
- Clear _cache_format in opcode.py (no inline caches)
- Fix getattro slot inheritance: preserve native slot from inherit_slots
- Fix BRANCH_RIGHT src_offset in InstrumentedPopJumpIf*
- Move lasti increment before line event for correct f_lineno
- Skip RESUME instruction from generating line events
- Defer stack pops via pending_stack_pops/pending_unwind_from_stack
  to avoid deadlock with state mutex
- Fix ForIter exhaust target in mark_stacks to skip END_FOR
- Prevent exception handler paths from overwriting normal-flow stacks
- Replace #[cfg(feature = "threading")] duplication with PyAtomic<T>
  from rustpython_common::atomic (Radium-based unified API)
- Remove expectedFailure from 31 now-passing jump tests
  • Loading branch information
youknowone committed Feb 27, 2026
commit 20a93c54c4b12a06b81562ff652c3ff387dcf8b0
3 changes: 2 additions & 1 deletion .cspell.dict/cpython.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ CLASSDEREF
classdict
cmpop
codedepth
constevaluator
CODEUNIT
CONIN
CONOUT
constevaluator
CONVFUNC
convparam
copyslot
Expand All @@ -62,6 +62,7 @@ fieldlist
fileutils
finalbody
finalizers
firsttraceable
flowgraph
formatfloat
freevar
Expand Down
69 changes: 0 additions & 69 deletions Lib/opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,75 +46,6 @@
hascompare = [opmap["COMPARE_OP"]]

_cache_format = {
"LOAD_GLOBAL": {
"counter": 1,
"index": 1,
"module_keys_version": 1,
"builtin_keys_version": 1,
},
"BINARY_OP": {
"counter": 1,
"descr": 4,
},
"UNPACK_SEQUENCE": {
"counter": 1,
},
"COMPARE_OP": {
"counter": 1,
},
"CONTAINS_OP": {
"counter": 1,
},
"FOR_ITER": {
"counter": 1,
},
"LOAD_SUPER_ATTR": {
"counter": 1,
},
"LOAD_ATTR": {
"counter": 1,
"version": 2,
"keys_version": 2,
"descr": 4,
},
"STORE_ATTR": {
"counter": 1,
"version": 2,
"index": 1,
},
"CALL": {
"counter": 1,
"func_version": 2,
},
"CALL_KW": {
"counter": 1,
"func_version": 2,
},
"STORE_SUBSCR": {
"counter": 1,
},
"SEND": {
"counter": 1,
},
"JUMP_BACKWARD": {
"counter": 1,
},
"TO_BOOL": {
"counter": 1,
"version": 2,
},
"POP_JUMP_IF_TRUE": {
"counter": 1,
},
"POP_JUMP_IF_FALSE": {
"counter": 1,
},
"POP_JUMP_IF_NONE": {
"counter": 1,
},
"POP_JUMP_IF_NOT_NONE": {
"counter": 1,
},
}

_inline_cache_entries = {
Expand Down
5 changes: 5 additions & 0 deletions Lib/test/dis_module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

# A simple module for testing the dis module.

def f(): pass
def g(): pass
5 changes: 2 additions & 3 deletions Lib/test/test_dis.py
Original file line number Diff line number Diff line change
Expand Up @@ -1147,7 +1147,6 @@ def test_intrinsic_2(self):
self.assertIn("CALL_INTRINSIC_2 1 (INTRINSIC_PREP_RERAISE_STAR)",
self.get_disassembly("try: pass\nexcept* Exception: x"))

@unittest.expectedFailure # TODO: RUSTPYTHON
def test_big_linenos(self):
def func(count):
namespace = {}
Expand Down Expand Up @@ -2119,7 +2118,6 @@ def test_oparg_alias(self):
positions=None)
self.assertEqual(instruction.arg, instruction.oparg)

@unittest.expectedFailure # TODO: RUSTPYTHON
def test_show_caches_with_label(self):
def f(x, y, z):
if x:
Expand Down Expand Up @@ -2238,6 +2236,7 @@ def f(opcode, oparg, offset, *init_args):
def get_instructions(self, code):
return dis._get_instructions_bytes(code)

@unittest.expectedFailure # TODO: RUSTPYTHON; no inline caches
def test_start_offset(self):
# When no extended args are present,
# start_offset should be equal to offset
Expand Down Expand Up @@ -2290,6 +2289,7 @@ def last_item(iterable):
self.assertEqual(14, instructions[6].offset)
self.assertEqual(8, instructions[6].start_offset)

@unittest.expectedFailure # TODO: RUSTPYTHON; no inline caches
def test_cache_offset_and_end_offset(self):
code = bytes([
opcode.opmap["LOAD_GLOBAL"], 0x01,
Expand Down Expand Up @@ -2422,7 +2422,6 @@ def test__find_imports(self):
self.assertEqual(len(res), 1)
self.assertEqual(res[0], expected)

@unittest.expectedFailure # TODO: RUSTPYTHON
def test__find_store_names(self):
cases = [
("x+y", ()),
Expand Down
13 changes: 4 additions & 9 deletions Lib/test/test_monitoring.py
Original file line number Diff line number Diff line change
Expand Up @@ -1744,7 +1744,6 @@ def func(v=1):
('branch right', 'func', 6, 8),
('branch right', 'func', 2, 10)])

@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: attribute 'f_lineno' of 'frame' objects is not writable
def test_callback_set_frame_lineno(self):
def func(s: str) -> int:
if s.startswith("t"):
Expand Down Expand Up @@ -1802,7 +1801,6 @@ def check_branches(self, run_func, test_func=None, tool=TEST_TOOL, recorders=BRA
for recorder in recorders:
sys.monitoring.register_callback(tool, recorder.event_type, None)

@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: 'code' object has no attribute 'co_branches'
def test_simple(self):

def func():
Expand All @@ -1823,7 +1821,6 @@ def whilefunc(n=0):

self.check_branches(whilefunc)

@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: 'code' object has no attribute 'co_branches'
def test_except_star(self):

class Foo:
Expand All @@ -1842,7 +1839,6 @@ def func():

self.check_branches(func)

@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: 'code' object has no attribute 'co_branches'
def test4(self):

def foo(n=0):
Expand All @@ -1853,7 +1849,6 @@ def foo(n=0):

self.check_branches(foo)

@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: 'code' object has no attribute 'co_branches'
def test_async_for(self):

async def gen():
Expand Down Expand Up @@ -1942,7 +1937,7 @@ def f():
]
return d["f"], expected

@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: False != True
@unittest.expectedFailure # TODO: RUSTPYTHON; line number differences in multi-line super() calls
def test_method_call(self):
nonopt_func, nonopt_expected = self._super_method_call(optimized=False)
opt_func, opt_expected = self._super_method_call(optimized=True)
Expand Down Expand Up @@ -1994,7 +1989,7 @@ def f():
]
return d["f"], expected

@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: False != True
@unittest.expectedFailure # TODO: RUSTPYTHON; line number differences in multi-line super() calls
def test_method_call_error(self):
nonopt_func, nonopt_expected = self._super_method_call_error(optimized=False)
opt_func, opt_expected = self._super_method_call_error(optimized=True)
Expand Down Expand Up @@ -2032,15 +2027,15 @@ def f():
]
return d["f"], expected

@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: False != True
@unittest.expectedFailure # TODO: RUSTPYTHON; line number differences in multi-line super() calls
def test_attr(self):
nonopt_func, nonopt_expected = self._super_attr(optimized=False)
opt_func, opt_expected = self._super_attr(optimized=True)

self.check_events(nonopt_func, recorders=self.RECORDERS, expected=nonopt_expected)
self.check_events(opt_func, recorders=self.RECORDERS, expected=opt_expected)

@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON; line number differences in multi-line super() calls
def test_vs_other_type_call(self):
code_template = textwrap.dedent("""
class C:
Expand Down
3 changes: 3 additions & 0 deletions Lib/test/test_peepholer.py
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,7 @@ def f(cond, true_value, false_value):
self.assertEqual(len(returns), 2)
self.check_lnotab(f)

@unittest.expectedFailure # TODO: RUSTPYTHON; absolute jump encoding
def test_elim_jump_to_uncond_jump(self):
# POP_JUMP_IF_FALSE to JUMP_FORWARD --> POP_JUMP_IF_FALSE to non-jump
def f():
Expand Down Expand Up @@ -640,12 +641,14 @@ def g()->1+1:
self.assertNotInBytecode(f, 'BINARY_OP')
self.check_lnotab(f)

@unittest.expectedFailure # TODO: RUSTPYTHON; no BUILD_LIST to BUILD_TUPLE optimization
def test_in_literal_list(self):
def containtest():
return x in [a, b]
self.assertEqual(count_instr_recursively(containtest, 'BUILD_LIST'), 0)
self.check_lnotab(containtest)

@unittest.expectedFailure # TODO: RUSTPYTHON; no BUILD_LIST to BUILD_TUPLE optimization
def test_iterate_literal_list(self):
def forloop():
for x in [a, b]:
Expand Down
Loading