Skip to content

Commit

Permalink
'backport' PyUnstable_Type_AssignVersionTag
Browse files Browse the repository at this point in the history
Summary: We already had this as `Ci_Type_AssignVersionTag`, but now that it exists upstream, adapt to the upstream name, tests, and header file to reduce friction in 3.12 upgrade.

Reviewed By: alexmalyshev

Differential Revision: D47202337

fbshipit-source-id: 4e527aecc2767fbdcd847355811104784ed9761d
  • Loading branch information
Carl Meyer authored and facebook-github-bot committed Jul 10, 2023
1 parent c99f32f commit 373a8a7
Show file tree
Hide file tree
Showing 10 changed files with 41 additions and 9 deletions.
2 changes: 0 additions & 2 deletions Cinder/Include/cinder/exports.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,6 @@ CiAPI_FUNC(PyObject *) Ci_Tuple_Repeat(PyTupleObject *, Py_ssize_t);

#define Ci_Py_TPFLAGS_FROZEN (1UL << 21)

CiAPI_FUNC(int) Ci_Type_AssignVersionTag(PyTypeObject *);

// Implementation in Python/bltinmodule.c
CiAPI_FUNC(PyObject *) builtin_next(PyObject *self, PyObject *const *args, Py_ssize_t nargs);

Expand Down
2 changes: 1 addition & 1 deletion Cinder/module/known-core-python-exported-symbols
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ Ci_ThreadState_SetProfileInterpAll
Ci_TupleHashItems
Ci_Tuple_Repeat
Ci_tuple_subscript
Ci_Type_AssignVersionTag
ClassDef_fields
Delete_fields
DictComp_fields
Expand Down Expand Up @@ -1992,6 +1991,7 @@ Py_UniversalNewlineFgets
PyUnstable_GC_VisitObjects
PyUnstable_PerfMapState_Fini
PyUnstable_PerfMapState_Init
PyUnstable_Type_AssignVersionTag
PyUnstable_WritePerfMapEntry
_Py_UTF8_Edit_Cost
_Py_VaBuildStack
Expand Down
7 changes: 7 additions & 0 deletions Include/cpython/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -564,3 +564,10 @@ PyAPI_FUNC(int) _PyTrash_cond(PyObject *op, destructor dealloc);
* unconditionally */
#define Py_TRASHCAN_SAFE_BEGIN(op) Py_TRASHCAN_BEGIN_CONDITION(op, 1)
#define Py_TRASHCAN_SAFE_END(op) Py_TRASHCAN_END

/* Attempt to assign a version tag to the given type.
*
* Returns 1 if the type already had a valid version tag or a new one was
* assigned, or 0 if a new tag could not be assigned.
*/
PyAPI_FUNC(int) PyUnstable_Type_AssignVersionTag(PyTypeObject *type);
2 changes: 1 addition & 1 deletion Jit/profile_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ void registerProfiledType(PyTypeObject* type) {
PyDictKeysObject* old_keys = ht->ht_cached_keys;
ht->ht_cached_keys = keys;
PyType_Modified(type);
Ci_Type_AssignVersionTag(type);
PyUnstable_Type_AssignVersionTag(type);
if (old_keys != nullptr) {
_PyDictKeys_DecRef(old_keys);
}
Expand Down
2 changes: 1 addition & 1 deletion Jit/type_deopt_patchers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ bool shouldPatchForAttr(
return true;
}

return !Ci_Type_AssignVersionTag(new_ty);
return !PyUnstable_Type_AssignVersionTag(new_ty);
}
} // namespace

Expand Down
2 changes: 1 addition & 1 deletion Jit/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ bool ensureVersionTag(BorrowedRef<PyTypeObject> type) {
return true;
}
ThreadedCompileSerialize guard;
return Ci_Type_AssignVersionTag(type);
return PyUnstable_Type_AssignVersionTag(type);
}

} // namespace jit
14 changes: 14 additions & 0 deletions Lib/test/test_type_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

# Skip this test if the _testcapi module isn't available.
type_get_version = import_helper.import_module('_testcapi').type_get_version
type_assign_version = import_helper.import_module('_testcapi').type_assign_version


@support.cpython_only
Expand Down Expand Up @@ -42,6 +43,19 @@ def test_tp_version_tag_unique(self):
self.assertEqual(len(set(all_version_tags)), 30,
msg=f"{all_version_tags} contains non-unique versions")

def test_type_assign_version(self):
class C:
x = 5

self.assertEqual(type_assign_version(C), 1)
c_ver = type_get_version(C)

C.x = 6
self.assertEqual(type_get_version(C), 0)
self.assertEqual(type_assign_version(C), 1)
self.assertNotEqual(type_get_version(C), 0)
self.assertNotEqual(type_get_version(C), c_ver)


if __name__ == "__main__":
support.run_unittest(TypeCacheTests)
13 changes: 13 additions & 0 deletions Modules/_testcapimodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -5818,6 +5818,18 @@ type_get_version(PyObject *self, PyObject *type)
}


static PyObject *
type_assign_version(PyObject *self, PyObject *type)
{
if (!PyType_Check(type)) {
PyErr_SetString(PyExc_TypeError, "argument must be a type");
return NULL;
}
int res = PyUnstable_Type_AssignVersionTag((PyTypeObject *)type);
return PyLong_FromLong(res);
}


static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *);
static PyObject *getargs_s_hash_int(PyObject *, PyObject *, PyObject*);

Expand Down Expand Up @@ -6899,6 +6911,7 @@ static PyMethodDef TestMethods[] = {
{"get_context_helpers_for_task", _get_context_helpers_for_task, METH_NOARGS},
{"test_dict_has_unsafe_keys", test_dict_has_unsafe_keys, METH_NOARGS},
{"type_get_version", type_get_version, METH_O, PyDoc_STR("type->tp_version_tag")},
{"type_assign_version", type_assign_version, METH_O, PyDoc_STR("PyUnstable_Type_AssignVersionTag")},
{"add_dict_watcher", add_dict_watcher, METH_O},
{"clear_dict_watcher", clear_dict_watcher, METH_O},
{"watch_dict", watch_dict, METH_VARARGS},
Expand Down
2 changes: 1 addition & 1 deletion Modules/gcmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2041,7 +2041,7 @@ immortalize_object(PyObject *obj, PyObject * /* unused */ args)
}

if (PyType_Check(obj)) {
Ci_Type_AssignVersionTag((PyTypeObject *)obj);
PyUnstable_Type_AssignVersionTag((PyTypeObject *)obj);
}
if (!_PyImmortal_RecursiveHeapWalk) {
return 0;
Expand Down
4 changes: 2 additions & 2 deletions Objects/typeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -522,8 +522,8 @@ assign_version_tag(struct type_cache *cache, PyTypeObject *type)
return 1;
}

int
Ci_Type_AssignVersionTag(PyTypeObject *type) {
int PyUnstable_Type_AssignVersionTag(PyTypeObject *type)
{
return assign_version_tag(get_type_cache(), type);
}

Expand Down

0 comments on commit 373a8a7

Please sign in to comment.