Skip to content

Commit b80a79b

Browse files
committed
add tests
1 parent 44f5c49 commit b80a79b

7 files changed

Lines changed: 230 additions & 108 deletions

File tree

Include/internal/pycore_uop_ids.h

Lines changed: 29 additions & 31 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_uop_metadata.h

Lines changed: 30 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/test_capi/test_opt.py

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3964,6 +3964,148 @@ class A:
39643964
self.assertIn("_INSERT_1_LOAD_CONST_INLINE_BORROW", uops)
39653965
self.assertEqual(count_ops(ex, "_POP_TOP_NOP"), 1)
39663966

3967+
def test_to_bool_kwargs_dict(self):
3968+
"""**kwargs is known to be dict, so TO_BOOL specializes to _TO_BOOL_DICT."""
3969+
def inner(**kwargs):
3970+
cnt = 0
3971+
for i in range(TIER2_THRESHOLD):
3972+
if kwargs:
3973+
cnt += 1
3974+
return cnt
3975+
3976+
def f(n):
3977+
return inner(a=1, b=2)
3978+
3979+
res, ex = self._run_with_optimizer(f, TIER2_THRESHOLD)
3980+
self.assertEqual(res, TIER2_THRESHOLD)
3981+
ex_inner = get_first_executor(inner)
3982+
self.assertIsNotNone(ex_inner)
3983+
uops = get_opnames(ex_inner)
3984+
self.assertIn("_TO_BOOL_DICT", uops)
3985+
self.assertNotIn("_TO_BOOL", uops)
3986+
3987+
def test_to_bool_kwargs_empty_dict(self):
3988+
"""**kwargs is known to be dict even when empty."""
3989+
def inner(**kwargs):
3990+
cnt = 0
3991+
for i in range(TIER2_THRESHOLD):
3992+
if not kwargs:
3993+
cnt += 1
3994+
return cnt
3995+
3996+
def f(n):
3997+
return inner()
3998+
3999+
res, ex = self._run_with_optimizer(f, TIER2_THRESHOLD)
4000+
self.assertEqual(res, TIER2_THRESHOLD)
4001+
ex_inner = get_first_executor(inner)
4002+
self.assertIsNotNone(ex_inner)
4003+
uops = get_opnames(ex_inner)
4004+
self.assertIn("_TO_BOOL_DICT", uops)
4005+
self.assertNotIn("_TO_BOOL", uops)
4006+
4007+
def test_to_bool_varargs_tuple(self):
4008+
"""*args is known to be tuple, so TO_BOOL specializes to _TO_BOOL_SIZED."""
4009+
def inner(*args):
4010+
cnt = 0
4011+
for i in range(TIER2_THRESHOLD):
4012+
if args:
4013+
cnt += 1
4014+
return cnt
4015+
4016+
def f(n):
4017+
return inner(1, 2, 3)
4018+
4019+
res, ex = self._run_with_optimizer(f, TIER2_THRESHOLD)
4020+
self.assertEqual(res, TIER2_THRESHOLD)
4021+
ex_inner = get_first_executor(inner)
4022+
self.assertIsNotNone(ex_inner)
4023+
uops = get_opnames(ex_inner)
4024+
self.assertIn("_TO_BOOL_SIZED", uops)
4025+
self.assertNotIn("_TO_BOOL", uops)
4026+
4027+
def test_to_bool_varargs_empty_tuple(self):
4028+
"""*args is known to be tuple even when empty."""
4029+
def inner(*args):
4030+
cnt = 0
4031+
for i in range(TIER2_THRESHOLD):
4032+
if not args:
4033+
cnt += 1
4034+
return cnt
4035+
4036+
def f(n):
4037+
return inner()
4038+
4039+
res, ex = self._run_with_optimizer(f, TIER2_THRESHOLD)
4040+
self.assertEqual(res, TIER2_THRESHOLD)
4041+
ex_inner = get_first_executor(inner)
4042+
self.assertIsNotNone(ex_inner)
4043+
uops = get_opnames(ex_inner)
4044+
self.assertIn("_TO_BOOL_SIZED", uops)
4045+
self.assertNotIn("_TO_BOOL", uops)
4046+
4047+
def test_to_bool_args_and_kwargs(self):
4048+
"""Combined *args and **kwargs both get correct types."""
4049+
def inner(*args, **kwargs):
4050+
cnt = 0
4051+
for i in range(TIER2_THRESHOLD):
4052+
if args and kwargs:
4053+
cnt += 1
4054+
return cnt
4055+
4056+
def f(n):
4057+
return inner(1, 2, a=3)
4058+
4059+
res, ex = self._run_with_optimizer(f, TIER2_THRESHOLD)
4060+
self.assertEqual(res, TIER2_THRESHOLD)
4061+
ex_inner = get_first_executor(inner)
4062+
self.assertIsNotNone(ex_inner)
4063+
uops = get_opnames(ex_inner)
4064+
self.assertIn("_TO_BOOL_SIZED", uops)
4065+
self.assertIn("_TO_BOOL_DICT", uops)
4066+
self.assertNotIn("_TO_BOOL", uops)
4067+
4068+
def test_to_bool_args_kwargs_with_regular_params(self):
4069+
"""*args/**kwargs slot calculation is correct with regular params."""
4070+
def inner(x, y, *args, key=None, **kwargs):
4071+
cnt = 0
4072+
for i in range(TIER2_THRESHOLD):
4073+
if args and kwargs:
4074+
cnt += 1
4075+
return cnt
4076+
4077+
def f(n):
4078+
return inner(1, 2, 3, 4, key="v", extra=5)
4079+
4080+
res, ex = self._run_with_optimizer(f, TIER2_THRESHOLD)
4081+
self.assertEqual(res, TIER2_THRESHOLD)
4082+
ex_inner = get_first_executor(inner)
4083+
self.assertIsNotNone(ex_inner)
4084+
uops = get_opnames(ex_inner)
4085+
self.assertIn("_TO_BOOL_SIZED", uops)
4086+
self.assertIn("_TO_BOOL_DICT", uops)
4087+
self.assertNotIn("_TO_BOOL", uops)
4088+
4089+
def test_to_bool_kwargs_only_no_varargs(self):
4090+
"""**kwargs without *args gets correct dict type."""
4091+
def inner(x, **kwargs):
4092+
cnt = 0
4093+
for i in range(TIER2_THRESHOLD):
4094+
if kwargs:
4095+
cnt += 1
4096+
return cnt
4097+
4098+
def f(n):
4099+
return inner(1, a=2)
4100+
4101+
res, ex = self._run_with_optimizer(f, TIER2_THRESHOLD)
4102+
self.assertEqual(res, TIER2_THRESHOLD)
4103+
ex_inner = get_first_executor(inner)
4104+
self.assertIsNotNone(ex_inner)
4105+
uops = get_opnames(ex_inner)
4106+
self.assertIn("_TO_BOOL_DICT", uops)
4107+
self.assertNotIn("_TO_BOOL", uops)
4108+
39674109
def test_attr_promotion_failure(self):
39684110
# We're not testing for any specific uops here, just
39694111
# testing it doesn't crash.

Python/bytecodes.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -601,23 +601,21 @@ dummy_func(
601601
_REPLACE_WITH_TRUE +
602602
POP_TOP;
603603

604-
tier2 op(_TO_BOOL_DICT, (value -- res, v)) {
604+
tier2 op(_TO_BOOL_DICT, (value -- res)) {
605605
PyObject *value_o = PyStackRef_AsPyObjectBorrow(value);
606606
assert(PyDict_CheckExact(value_o));
607607
STAT_INC(TO_BOOL, hit);
608608
res = PyDict_GET_SIZE(value_o) ? PyStackRef_True : PyStackRef_False;
609-
v = value;
610-
DEAD(value);
609+
PyStackRef_CLOSE(value);
611610
}
612611

613-
tier2 op(_TO_BOOL_SIZED, (value -- res, v)) {
612+
tier2 op(_TO_BOOL_SIZED, (value -- res)) {
614613
/* Covers types whose truthiness is Py_SIZE(obj) != 0:
615614
tuple, set, frozenset, bytes, bytearray. */
616615
PyObject *value_o = PyStackRef_AsPyObjectBorrow(value);
617616
STAT_INC(TO_BOOL, hit);
618617
res = Py_SIZE(value_o) ? PyStackRef_True : PyStackRef_False;
619-
v = value;
620-
DEAD(value);
618+
PyStackRef_CLOSE(value);
621619
}
622620

623621
macro(UNARY_INVERT) = _UNARY_INVERT + POP_TOP;

0 commit comments

Comments
 (0)