Skip to content

Commit b0fa60e

Browse files
committed
Address review comments
1 parent 436a6fc commit b0fa60e

File tree

1 file changed

+142
-15
lines changed

1 file changed

+142
-15
lines changed

Python/optimizer_symbols.c

Lines changed: 142 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -326,16 +326,21 @@ _Py_uop_sym_set_type(JitOptContext *ctx, JitOptRef ref, PyTypeObject *typ)
326326
case JIT_SYM_RECORDED_VALUE_TAG:
327327
if (Py_TYPE(sym->recorded_value.value) == typ) {
328328
sym->recorded_value.known_type = true;
329-
return;
330329
}
331-
sym->tag = JIT_SYM_KNOWN_CLASS_TAG;
332-
sym->cls.version = 0;
333-
sym->cls.type = typ;
330+
else {
331+
sym_set_bottom(ctx, sym);
332+
}
334333
return;
335334
case JIT_SYM_RECORDED_TYPE_TAG:
336-
/* The given value might contradict the recorded one,
337-
* in which case we could return bottom.
338-
* Just discard the recorded value for now */
335+
if (sym->recorded_type.type == typ) {
336+
sym->tag = JIT_SYM_KNOWN_CLASS_TAG;
337+
sym->cls.version = 0;
338+
sym->cls.type = typ;
339+
}
340+
else {
341+
sym_set_bottom(ctx, sym);
342+
}
343+
return;
339344
case JIT_SYM_NON_NULL_TAG:
340345
case JIT_SYM_UNKNOWN_TAG:
341346
sym->tag = JIT_SYM_KNOWN_CLASS_TAG;
@@ -429,23 +434,23 @@ _Py_uop_sym_set_type_version(JitOptContext *ctx, JitOptRef ref, unsigned int ver
429434
sym->tag = JIT_SYM_KNOWN_CLASS_TAG;
430435
sym->cls.type = Py_TYPE(sym->recorded_value.value);
431436
sym->cls.version = version;
437+
return true;
432438
}
433439
else {
434-
sym->tag = JIT_SYM_TYPE_VERSION_TAG;
435-
sym->version.version = version;
440+
sym_set_bottom(ctx, sym);
441+
return false;
436442
}
437-
return true;
438443
case JIT_SYM_RECORDED_TYPE_TAG:
439444
if (sym->recorded_type.type->tp_version_tag == version) {
440445
sym->tag = JIT_SYM_KNOWN_CLASS_TAG;
441446
sym->cls.type = sym->recorded_type.type;
442447
sym->cls.version = version;
448+
return true;
443449
}
444450
else {
445-
sym->tag = JIT_SYM_TYPE_VERSION_TAG;
446-
sym->version.version = version;
451+
sym_set_bottom(ctx, sym);
452+
return false;
447453
}
448-
return true;
449454
}
450455
Py_UNREACHABLE();
451456
}
@@ -658,7 +663,6 @@ _Py_uop_sym_get_type(JitOptRef ref)
658663
case JIT_SYM_NON_NULL_TAG:
659664
case JIT_SYM_UNKNOWN_TAG:
660665
case JIT_SYM_RECORDED_TYPE_TAG:
661-
case JIT_SYM_RECORDED_GEN_FUNC_TAG:
662666
return NULL;
663667
case JIT_SYM_RECORDED_VALUE_TAG:
664668
if (sym->recorded_value.known_type) {
@@ -678,6 +682,8 @@ _Py_uop_sym_get_type(JitOptRef ref)
678682
return &PyBool_Type;
679683
case JIT_SYM_COMPACT_INT:
680684
return &PyLong_Type;
685+
case JIT_SYM_RECORDED_GEN_FUNC_TAG:
686+
return &PyGen_Type;
681687
}
682688
Py_UNREACHABLE();
683689
}
@@ -1127,6 +1133,9 @@ _Py_uop_sym_set_recorded_value(JitOptContext *ctx, JitOptRef ref, PyObject *valu
11271133
sym->recorded_value.known_type = true;
11281134
sym->recorded_value.value = value;
11291135
}
1136+
else {
1137+
sym_set_bottom(ctx, sym);
1138+
}
11301139
return;
11311140
case JIT_SYM_KNOWN_VALUE_TAG:
11321141
return;
@@ -1136,6 +1145,9 @@ _Py_uop_sym_set_recorded_value(JitOptContext *ctx, JitOptRef ref, PyObject *valu
11361145
sym->recorded_value.known_type = true;
11371146
sym->recorded_value.value = value;
11381147
}
1148+
else {
1149+
sym_set_bottom(ctx, sym);
1150+
}
11391151
return;
11401152
// In these cases the original information is more valuable
11411153
case JIT_SYM_RECORDED_GEN_FUNC_TAG:
@@ -1189,6 +1201,9 @@ _Py_uop_sym_set_recorded_gen_func(JitOptContext *ctx, JitOptRef ref, PyFunctionO
11891201
sym->tag = JIT_SYM_RECORDED_GEN_FUNC_TAG;
11901202
sym->recorded_gen_func.func = value;
11911203
}
1204+
else {
1205+
sym_set_bottom(ctx, sym);
1206+
}
11921207
return;
11931208
case JIT_SYM_TYPE_VERSION_TAG:
11941209
if (sym->version.version == PyGen_Type.tp_version_tag) {
@@ -1249,6 +1264,9 @@ _Py_uop_sym_set_recorded_type(JitOptContext *ctx, JitOptRef ref, PyTypeObject *t
12491264
sym->tag = JIT_SYM_KNOWN_CLASS_TAG;
12501265
sym->cls.type = type;
12511266
}
1267+
else {
1268+
sym_set_bottom(ctx, sym);
1269+
}
12521270
return;
12531271
// In these cases the original information is more valuable
12541272
case JIT_SYM_TUPLE_TAG:
@@ -1461,6 +1479,7 @@ _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
14611479
PyObject *val_43 = NULL;
14621480
PyObject *val_big = NULL;
14631481
PyObject *tuple = NULL;
1482+
PyFunctionObject *func = NULL;
14641483

14651484
// Use a single 'sym' variable so copy-pasting tests is easier.
14661485
JitOptRef ref = _Py_uop_sym_new_unknown(ctx);
@@ -1871,19 +1890,127 @@ _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
18711890
TEST_PREDICATE(_Py_uop_sym_matches_type(ref_int, &PyLong_Type), "43 is not an int");
18721891
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, ref_int) == val_43, "43 isn't 43");
18731892

1893+
// Test recorded values
1894+
1895+
/* Test that recorded values aren't treated as known values*/
1896+
JitOptRef rv1 = _Py_uop_sym_new_unknown(ctx);
1897+
_Py_uop_sym_set_recorded_value(ctx, rv1, val_42);
1898+
TEST_PREDICATE(!_Py_uop_sym_matches_type(rv1, &PyLong_Type), "recorded value is treated as known");
1899+
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rv1) == NULL, "recorded value is treated as known");
1900+
TEST_PREDICATE(!_Py_uop_sym_is_compact_int(rv1), "recorded value is treated as known");
1901+
1902+
/* Test that setting type or value narrows correctly */
1903+
JitOptRef rv2 = _Py_uop_sym_new_unknown(ctx);
1904+
_Py_uop_sym_set_recorded_value(ctx, rv2, val_42);
1905+
_Py_uop_sym_set_const(ctx, rv2, val_42);
1906+
TEST_PREDICATE(_Py_uop_sym_matches_type(rv2, &PyLong_Type), "recorded value doesn't narrow");
1907+
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rv2) == val_42, "recorded value doesn't narrow");
1908+
1909+
JitOptRef rv3 = _Py_uop_sym_new_unknown(ctx);
1910+
_Py_uop_sym_set_recorded_value(ctx, rv3, val_42);
1911+
_Py_uop_sym_set_type(ctx, rv3, &PyLong_Type);
1912+
TEST_PREDICATE(_Py_uop_sym_matches_type(rv3, &PyLong_Type), "recorded value doesn't narrow");
1913+
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rv3) == NULL, "recorded value with type is treated as known");
1914+
1915+
JitOptRef rv4 = _Py_uop_sym_new_unknown(ctx);
1916+
_Py_uop_sym_set_recorded_value(ctx, rv4, val_42);
1917+
_Py_uop_sym_set_type_version(ctx, rv4, PyLong_Type.tp_version_tag);
1918+
TEST_PREDICATE(_Py_uop_sym_matches_type(rv4, &PyLong_Type), "recorded value doesn't narrow");
1919+
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rv4) == NULL, "recorded value with type is treated as known");
1920+
1921+
// test recorded types
1922+
1923+
/* Test that recorded type aren't treated as known values*/
1924+
JitOptRef rt1 = _Py_uop_sym_new_unknown(ctx);
1925+
_Py_uop_sym_set_recorded_type(ctx, rt1, &PyLong_Type);
1926+
TEST_PREDICATE(!_Py_uop_sym_matches_type(rt1, &PyLong_Type), "recorded type is treated as known");
1927+
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rt1) == NULL, "recorded type is treated as known value");
1928+
1929+
/* Test that setting type or value narrows correctly */
1930+
JitOptRef rt2 = _Py_uop_sym_new_unknown(ctx);
1931+
_Py_uop_sym_set_recorded_type(ctx, rt2, &PyLong_Type);
1932+
_Py_uop_sym_set_const(ctx, rt2, val_42);
1933+
TEST_PREDICATE(_Py_uop_sym_matches_type(rt2, &PyLong_Type), "recorded value doesn't narrow");
1934+
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rt2) == val_42, "recorded value doesn't narrow");
1935+
1936+
JitOptRef rt3 = _Py_uop_sym_new_unknown(ctx);
1937+
_Py_uop_sym_set_recorded_type(ctx, rt3, &PyLong_Type);
1938+
_Py_uop_sym_set_type(ctx, rt3, &PyLong_Type);
1939+
TEST_PREDICATE(_Py_uop_sym_matches_type(rt3, &PyLong_Type), "recorded value doesn't narrow");
1940+
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rt3) == NULL, "known type is treated as known value");
1941+
1942+
JitOptRef rt4 = _Py_uop_sym_new_unknown(ctx);
1943+
_Py_uop_sym_set_recorded_type(ctx, rt4, &PyLong_Type);
1944+
_Py_uop_sym_set_type_version(ctx, rt4, PyLong_Type.tp_version_tag);
1945+
TEST_PREDICATE(_Py_uop_sym_matches_type(rt4, &PyLong_Type), "recorded value doesn't narrow");
1946+
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rt4) == NULL, "recorded value with type is treated as known");
1947+
1948+
// test recorded gen function
1949+
1950+
PyObject *dict = PyDict_New();
1951+
if (dict == NULL) {
1952+
goto fail;
1953+
}
1954+
PyCodeObject *code = PyCode_NewEmpty(__FILE__, "uop_symbols_test", __LINE__);
1955+
if (code == NULL) {
1956+
goto fail;
1957+
}
1958+
func = (PyFunctionObject *)PyFunction_New((PyObject *)code, dict);
1959+
if (func == NULL) {
1960+
goto fail;
1961+
}
1962+
1963+
/* Test that recorded type aren't treated as known values*/
1964+
JitOptRef rg1 = _Py_uop_sym_new_unknown(ctx);
1965+
_Py_uop_sym_set_recorded_gen_func(ctx, rg1, func);
1966+
TEST_PREDICATE(_Py_uop_sym_matches_type(rg1, &PyGen_Type), "recorded gen func not treated as generator");
1967+
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rg1) == NULL, "recorded gen func is treated as known value");
1968+
1969+
/* Test that setting type narrows correctly */
1970+
1971+
JitOptRef rg2 = _Py_uop_sym_new_unknown(ctx);
1972+
_Py_uop_sym_set_recorded_gen_func(ctx, rg2, func);
1973+
_Py_uop_sym_set_type(ctx, rg2, &PyGen_Type);
1974+
TEST_PREDICATE(_Py_uop_sym_matches_type(rg1, &PyGen_Type), "recorded gen func not treated as generator");
1975+
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rg2) == NULL, "known type is treated as known value");
1976+
1977+
JitOptRef rg3 = _Py_uop_sym_new_unknown(ctx);
1978+
_Py_uop_sym_set_recorded_gen_func(ctx, rg3, func);
1979+
_Py_uop_sym_set_type_version(ctx, rg3, PyGen_Type.tp_version_tag);
1980+
TEST_PREDICATE(_Py_uop_sym_matches_type(rg1, &PyGen_Type), "recorded gen func not treated as generator");
1981+
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, rg3) == NULL, "recorded value with type is treated as known");
1982+
1983+
/* Test contradictions */
1984+
_Py_uop_sym_set_type(ctx, rv1, &PyFloat_Type);
1985+
TEST_PREDICATE(_Py_uop_sym_is_bottom(rv1), "recorded value cast to other type isn't bottom");
1986+
_Py_uop_sym_set_type_version(ctx, rv2, PyFloat_Type.tp_version_tag);
1987+
TEST_PREDICATE(_Py_uop_sym_is_bottom(rv2), "recorded value cast to other type version isn't bottom");
1988+
1989+
_Py_uop_sym_set_type(ctx, rt1, &PyFloat_Type);
1990+
TEST_PREDICATE(_Py_uop_sym_is_bottom(rv1), "recorded type cast to other type isn't bottom");
1991+
_Py_uop_sym_set_type_version(ctx, rt2, PyFloat_Type.tp_version_tag);
1992+
TEST_PREDICATE(_Py_uop_sym_is_bottom(rv2), "recorded type cast to other type version isn't bottom");
1993+
1994+
_Py_uop_sym_set_type(ctx, rg1, &PyFloat_Type);
1995+
TEST_PREDICATE(_Py_uop_sym_is_bottom(rg1), "recorded gen func cast to other type isn't bottom");
1996+
_Py_uop_sym_set_type_version(ctx, rg2, PyFloat_Type.tp_version_tag);
1997+
TEST_PREDICATE(_Py_uop_sym_is_bottom(rg2), "recorded gen func cast to other type version isn't bottom");
1998+
18741999
_Py_uop_abstractcontext_fini(ctx);
18752000
Py_DECREF(val_42);
18762001
Py_DECREF(val_43);
18772002
Py_DECREF(val_big);
18782003
Py_DECREF(tuple);
2004+
Py_DECREF(func);
18792005
Py_RETURN_NONE;
18802006

18812007
fail:
18822008
_Py_uop_abstractcontext_fini(ctx);
18832009
Py_XDECREF(val_42);
18842010
Py_XDECREF(val_43);
18852011
Py_XDECREF(val_big);
1886-
Py_DECREF(tuple);
2012+
Py_XDECREF(tuple);
2013+
Py_XDECREF(func);
18872014
return NULL;
18882015
}
18892016

0 commit comments

Comments
 (0)