Skip to content

Commit 1a958a8

Browse files
committed
Also set the type when setting the type version
1 parent 5ab66a8 commit 1a958a8

File tree

4 files changed

+66
-10
lines changed

4 files changed

+66
-10
lines changed

Lib/test/test_capi/test_opt.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2093,6 +2093,25 @@ def testfunc(n):
20932093
self.assertNotIn("_TO_BOOL_BOOL", uops)
20942094
self.assertIn("_GUARD_IS_TRUE_POP", uops)
20952095

2096+
def test_set_type_version_sets_type(self):
2097+
class C:
2098+
A = 1
2099+
2100+
def testfunc(n):
2101+
x = 0
2102+
c = C()
2103+
for _ in range(n):
2104+
x += c.A # Guarded.
2105+
x += type(c).A # Unguarded!
2106+
return x
2107+
2108+
res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
2109+
self.assertEqual(res, 2 * TIER2_THRESHOLD)
2110+
self.assertIsNotNone(ex)
2111+
uops = get_opnames(ex)
2112+
self.assertIn("_GUARD_TYPE_VERSION", uops)
2113+
self.assertNotIn("_CHECK_ATTR_CLASS", uops)
2114+
20962115

20972116
def global_identity(x):
20982117
return x

Python/optimizer_bytecodes.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,18 @@ dummy_func(void) {
118118
sym_set_type(left, &PyLong_Type);
119119
}
120120

121+
op(_CHECK_ATTR_CLASS, (type_version/2, owner -- owner)) {
122+
PyObject *type = (PyObject *)_PyType_LookupByVersion(type_version);
123+
if (type) {
124+
if (type == sym_get_const(ctx, owner)) {
125+
REPLACE_OP(this_instr, _NOP, 0, 0);
126+
}
127+
else {
128+
sym_set_const(owner, type);
129+
}
130+
}
131+
}
132+
121133
op(_GUARD_TYPE_VERSION, (type_version/2, owner -- owner)) {
122134
assert(type_version);
123135
if (sym_matches_type_version(owner, type_version)) {

Python/optimizer_cases.c.h

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

Python/optimizer_symbols.c

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,10 @@ _Py_uop_sym_set_type(JitOptContext *ctx, JitOptSymbol *sym, PyTypeObject *typ)
200200
bool
201201
_Py_uop_sym_set_type_version(JitOptContext *ctx, JitOptSymbol *sym, unsigned int version)
202202
{
203+
PyTypeObject *type = _PyType_LookupByVersion(version);
204+
if (type) {
205+
_Py_uop_sym_set_type(ctx, sym, type);
206+
}
203207
JitSymType tag = sym->tag;
204208
switch(tag) {
205209
case JIT_SYM_NULL_TAG:
@@ -215,18 +219,23 @@ _Py_uop_sym_set_type_version(JitOptContext *ctx, JitOptSymbol *sym, unsigned int
215219
return true;
216220
}
217221
case JIT_SYM_KNOWN_VALUE_TAG:
218-
Py_CLEAR(sym->value.value);
219-
sym_set_bottom(ctx, sym);
220-
return false;
222+
if (Py_TYPE(sym->value.value)->tp_version_tag != version) {
223+
sym_set_bottom(ctx, sym);
224+
return false;
225+
};
226+
return true;
221227
case JIT_SYM_TUPLE_TAG:
222-
sym_set_bottom(ctx, sym);
223-
return false;
228+
if (PyTuple_Type.tp_version_tag != version) {
229+
sym_set_bottom(ctx, sym);
230+
return false;
231+
};
232+
return true;
224233
case JIT_SYM_TYPE_VERSION_TAG:
225-
if (sym->version.version == version) {
226-
return true;
234+
if (sym->version.version != version) {
235+
sym_set_bottom(ctx, sym);
236+
return false;
227237
}
228-
sym_set_bottom(ctx, sym);
229-
return false;
238+
return true;
230239
case JIT_SYM_BOTTOM_TAG:
231240
return false;
232241
case JIT_SYM_NON_NULL_TAG:
@@ -266,7 +275,11 @@ _Py_uop_sym_set_const(JitOptContext *ctx, JitOptSymbol *sym, PyObject *const_val
266275
}
267276
return;
268277
case JIT_SYM_TUPLE_TAG:
269-
sym_set_bottom(ctx, sym);
278+
if (Py_TYPE(const_val) != &PyTuple_Type) {
279+
sym_set_bottom(ctx, sym);
280+
return;
281+
}
282+
make_const(sym, const_val);
270283
return;
271284
case JIT_SYM_TYPE_VERSION_TAG:
272285
if (sym->version.version != Py_TYPE(const_val)->tp_version_tag) {

0 commit comments

Comments
 (0)