Skip to content
Open
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
refactor
  • Loading branch information
eendebakpt committed Apr 4, 2026
commit d52937f8e039616353daf85fd41c18ae9f470dda
25 changes: 25 additions & 0 deletions Lib/test/test_capi/test_opt.py
Original file line number Diff line number Diff line change
Expand Up @@ -4021,6 +4021,31 @@ def testfunc(n):
self.assertIn("_TO_BOOL_DICT", uops)
self.assertNotIn("_TO_BOOL", uops)

def test_guard_type_version_resolves_type_for_to_bool(self):
# Tests the _GUARD_TYPE_VERSION + _RECORD_TOS_TYPE flow:
# TO_BOOL_GENERIC records the type, then _GUARD_TYPE_VERSION
# resolves it (even if the version cache has a collision),
# enabling the optimizer to specialize _TO_BOOL → _TO_BOOL_DICT.
def testfunc(n):
d = {"key": "value"}
count = 0
for _ in range(n):
if d:
count += 1
d["key"] = "value" # mutation keeps dict non-trivial
return count

res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
self.assertEqual(res, TIER2_THRESHOLD)
self.assertIsNotNone(ex)
uops = get_opnames(ex)
# The optimizer should resolve the dict type from recorded type
# info and specialize _TO_BOOL into _TO_BOOL_DICT
self.assertIn("_TO_BOOL_DICT", uops)
self.assertNotIn("_TO_BOOL", uops)
# _GUARD_TYPE_VERSION should be present (guards the dict type)
self.assertIn("_GUARD_TYPE_VERSION", uops)

def test_attr_promotion_failure(self):
# We're not testing for any specific uops here, just
# testing it doesn't crash.
Expand Down
3 changes: 2 additions & 1 deletion Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -557,8 +557,9 @@ dummy_func(
tier2 pure op(_TO_BOOL_DICT, (value -- res)) {
PyObject *value_o = PyStackRef_AsPyObjectBorrow(value);
assert(PyAnyDict_CheckExact(value_o));
PyStackRef_CLOSE(value);
STAT_INC(TO_BOOL, hit);
res = ((PyDictObject *)value_o)->ma_used ? PyStackRef_True : PyStackRef_False;
PyStackRef_CLOSE(value);
}

inst(TO_BOOL_NONE, (unused/1, unused/2, value -- res)) {
Expand Down
8 changes: 7 additions & 1 deletion Python/executor_cases.c.h

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

4 changes: 2 additions & 2 deletions Python/specialize.c
Original file line number Diff line number Diff line change
Expand Up @@ -2699,7 +2699,7 @@ to_bool_fail_kind(PyObject *value)
#endif // Py_STATS

static int
check_type_always_succeeds(PyTypeObject *ty)
check_type_noop(PyTypeObject *ty)
{
(void)ty;
return 0;
Expand Down Expand Up @@ -2771,7 +2771,7 @@ _Py_Specialize_ToBool(_PyStackRef value_o, _Py_CODEUNIT *instr)
unsigned int version;
if (PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE)) {
version = 0;
int err = _PyType_Validate(tp, check_type_always_succeeds, &version);
int err = _PyType_Validate(tp, check_type_noop, &version);
if (err < 0) {
SPECIALIZATION_FAIL(TO_BOOL, SPEC_FAIL_OUT_OF_VERSIONS);
goto failure;
Expand Down