Skip to content

Commit ed5c365

Browse files
committed
F: Regions: Migrated object.c - so many barriers
1 parent c4e4f5e commit ed5c365

7 files changed

Lines changed: 140 additions & 27 deletions

File tree

Include/internal/pycore_object.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,6 +1018,7 @@ _PyObject_ManagedDictPointer(PyObject *obj)
10181018
static inline PyDictObject *
10191019
_PyObject_GetManagedDict(PyObject *obj)
10201020
{
1021+
// Pyrona: This returns a borrowed reference
10211022
PyManagedDictPointer *dorv = _PyObject_ManagedDictPointer(obj);
10221023
return (PyDictObject *)FT_ATOMIC_LOAD_PTR_ACQUIRE(dorv->dict);
10231024
}

Objects/dictobject.c

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7495,6 +7495,7 @@ store_instance_attr_dict(PyObject *obj, PyDictObject *dict, PyObject *name, PyOb
74957495
int
74967496
_PyObject_StoreInstanceAttribute(PyObject *obj, PyObject *name, PyObject *value)
74977497
{
7498+
// Pyrona: This functions was checked and no further migration is needed
74987499
PyDictValues *values = _PyObject_InlineValues(obj);
74997500
if (!FT_ATOMIC_LOAD_UINT8(values->valid)) {
75007501
PyDictObject *dict = _PyObject_GetManagedDict(obj);
@@ -7578,6 +7579,7 @@ _PyObject_ManagedDictValidityCheck(PyObject *obj)
75787579
bool
75797580
_PyObject_TryGetInstanceAttribute(PyObject *obj, PyObject *name, PyObject **attr)
75807581
{
7582+
// Pyrona: This functions was checked and no further migration is needed
75817583
assert(PyUnicode_CheckExact(name));
75827584
PyDictValues *values = _PyObject_InlineValues(obj);
75837585
if (!FT_ATOMIC_LOAD_UINT8(values->valid)) {
@@ -7724,17 +7726,25 @@ clear_inline_values(PyObject *dict, PyDictValues *values)
77247726
}
77257727
}
77267728

7727-
static void
7729+
static int
77287730
set_dict_inline_values(PyObject *obj, PyDictObject *new_dict)
77297731
{
7732+
// Pyrona: This functions was checked and no further migration is needed
77307733
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(obj);
77317734

77327735
PyDictValues *values = _PyObject_InlineValues(obj);
77337736

7737+
// Regions: The given dictionary should always be in the local region or NULL.
7738+
// This call should always succeed. Since this is a private funciton we changed
7739+
// it to be failable to support other circumstances
7740+
if (PyRegion_AddRef(obj, new_dict)) {
7741+
return -1;
7742+
}
77347743
Py_XINCREF(new_dict);
77357744
FT_ATOMIC_STORE_PTR(_PyObject_ManagedDictPointer(obj)->dict, new_dict);
77367745

77377746
clear_inline_values(obj, values);
7747+
return 0;
77387748
}
77397749

77407750
#ifdef Py_GIL_DISABLED
@@ -7815,6 +7825,7 @@ decref_maybe_delay(PyObject *obj, bool delay)
78157825
int
78167826
_PyObject_SetManagedDict(PyObject *obj, PyObject *new_dict)
78177827
{
7828+
// Pyrona: This functions was checked and no further migration is needed
78187829
assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
78197830
#ifndef NDEBUG
78207831
Py_BEGIN_CRITICAL_SECTION(obj);
@@ -7863,17 +7874,27 @@ _PyObject_SetManagedDict(PyObject *obj, PyObject *new_dict)
78637874

78647875
return 0;
78657876
#else
7877+
if (!(PyRegion_IsLocal(new_dict) || PyRegion_SameRegion(obj, new_dict) || new_dict == NULL)) {
7878+
PyErr_Format(PyExc_RuntimeError,
7879+
"new dict must be local, in the same region as the object, or NULL, "
7880+
"got object=%R and new_dict=%R", obj, new_dict);
7881+
return -1;
7882+
}
78667883
PyDictObject *dict = _PyObject_GetManagedDict(obj);
78677884
if (dict == NULL) {
7868-
set_dict_inline_values(obj, (PyDictObject *)new_dict);
7869-
return 0;
7885+
return set_dict_inline_values(obj, (PyDictObject *)new_dict);
78707886
}
78717887
if (_PyDict_DetachFromObject(dict, obj) == 0) {
7888+
// Regions: The function above moves all objects into `dict`. On failure,
7889+
// dict remains set. The failure should therefore not clear the fields
7890+
// but only move them into the managed dict.
7891+
// This should always succeed, due to the local or same region check above.
78727892
if (PyRegion_AddRef(obj, new_dict)) {
78737893
return -1;
78747894
}
78757895
_PyObject_ManagedDictPointer(obj)->dict = (PyDictObject *)Py_XNewRef(new_dict);
78767896
PyRegion_RemoveRef(obj, dict);
7897+
Py_DECREF(dict);
78777898
return 0;
78787899
}
78797900
assert(new_dict == NULL);
@@ -7903,9 +7924,20 @@ _PyObject_SetManagedDict(PyObject *obj, PyObject *new_dict)
79037924
static int
79047925
detach_dict_from_object(PyDictObject *mp, PyObject *obj)
79057926
{
7927+
// Pyrona: This functions was checked and no further migration is needed
79067928
assert(_PyObject_ManagedDictPointer(obj)->dict == mp);
79077929
assert(_PyObject_InlineValuesConsistencyCheck(obj));
79087930

7931+
// Immutability: During deallocation of immutable objects, the object is
7932+
// unfrozen. Here is can happen that the object itself is turned mutable
7933+
// while the dict stayed immutable. This case explicitly allows this.
7934+
if (!(PyRegion_SameRegion(mp, obj) || (!_Py_IsImmutable(obj) && _Py_IsImmutable(mp)))) {
7935+
PyErr_Format(PyExc_RuntimeError,
7936+
"the instance dictionary has to be in the same region as the object"
7937+
"got object=%R and dict=%R", obj, mp);
7938+
return -1;
7939+
}
7940+
79097941
if (FT_ATOMIC_LOAD_PTR_RELAXED(mp->ma_values) != _PyObject_InlineValues(obj)) {
79107942
return 0;
79117943
}
@@ -7980,6 +8012,7 @@ PyObject_ClearManagedDict(PyObject *obj)
79808012
int
79818013
_PyDict_DetachFromObject(PyDictObject *mp, PyObject *obj)
79828014
{
8015+
// Pyrona: This functions was checked and no further migration is needed
79838016
ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(obj);
79848017

79858018
return detach_dict_from_object(mp, obj);
@@ -8264,6 +8297,7 @@ _PyDict_SendEvent(int watcher_bits,
82648297
static int
82658298
_PyObject_InlineValuesConsistencyCheck(PyObject *obj)
82668299
{
8300+
// Pyrona: This functions was checked and no further migration is needed
82678301
if ((Py_TYPE(obj)->tp_flags & Py_TPFLAGS_INLINE_VALUES) == 0) {
82688302
return 1;
82698303
}

0 commit comments

Comments
 (0)