Skip to content

Commit d52937f

Browse files
committed
refactor
1 parent 8e62e9f commit d52937f

File tree

4 files changed

+36
-4
lines changed

4 files changed

+36
-4
lines changed

Lib/test/test_capi/test_opt.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4021,6 +4021,31 @@ def testfunc(n):
40214021
self.assertIn("_TO_BOOL_DICT", uops)
40224022
self.assertNotIn("_TO_BOOL", uops)
40234023

4024+
def test_guard_type_version_resolves_type_for_to_bool(self):
4025+
# Tests the _GUARD_TYPE_VERSION + _RECORD_TOS_TYPE flow:
4026+
# TO_BOOL_GENERIC records the type, then _GUARD_TYPE_VERSION
4027+
# resolves it (even if the version cache has a collision),
4028+
# enabling the optimizer to specialize _TO_BOOL → _TO_BOOL_DICT.
4029+
def testfunc(n):
4030+
d = {"key": "value"}
4031+
count = 0
4032+
for _ in range(n):
4033+
if d:
4034+
count += 1
4035+
d["key"] = "value" # mutation keeps dict non-trivial
4036+
return count
4037+
4038+
res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
4039+
self.assertEqual(res, TIER2_THRESHOLD)
4040+
self.assertIsNotNone(ex)
4041+
uops = get_opnames(ex)
4042+
# The optimizer should resolve the dict type from recorded type
4043+
# info and specialize _TO_BOOL into _TO_BOOL_DICT
4044+
self.assertIn("_TO_BOOL_DICT", uops)
4045+
self.assertNotIn("_TO_BOOL", uops)
4046+
# _GUARD_TYPE_VERSION should be present (guards the dict type)
4047+
self.assertIn("_GUARD_TYPE_VERSION", uops)
4048+
40244049
def test_attr_promotion_failure(self):
40254050
# We're not testing for any specific uops here, just
40264051
# testing it doesn't crash.

Python/bytecodes.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,8 +557,9 @@ dummy_func(
557557
tier2 pure op(_TO_BOOL_DICT, (value -- res)) {
558558
PyObject *value_o = PyStackRef_AsPyObjectBorrow(value);
559559
assert(PyAnyDict_CheckExact(value_o));
560-
PyStackRef_CLOSE(value);
560+
STAT_INC(TO_BOOL, hit);
561561
res = ((PyDictObject *)value_o)->ma_used ? PyStackRef_True : PyStackRef_False;
562+
PyStackRef_CLOSE(value);
562563
}
563564

564565
inst(TO_BOOL_NONE, (unused/1, unused/2, value -- res)) {

Python/executor_cases.c.h

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/specialize.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2699,7 +2699,7 @@ to_bool_fail_kind(PyObject *value)
26992699
#endif // Py_STATS
27002700

27012701
static int
2702-
check_type_always_succeeds(PyTypeObject *ty)
2702+
check_type_noop(PyTypeObject *ty)
27032703
{
27042704
(void)ty;
27052705
return 0;
@@ -2771,7 +2771,7 @@ _Py_Specialize_ToBool(_PyStackRef value_o, _Py_CODEUNIT *instr)
27712771
unsigned int version;
27722772
if (PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE)) {
27732773
version = 0;
2774-
int err = _PyType_Validate(tp, check_type_always_succeeds, &version);
2774+
int err = _PyType_Validate(tp, check_type_noop, &version);
27752775
if (err < 0) {
27762776
SPECIALIZATION_FAIL(TO_BOOL, SPEC_FAIL_OUT_OF_VERSIONS);
27772777
goto failure;

0 commit comments

Comments
 (0)