Skip to content

Commit b47926d

Browse files
WIP Adding WB to object.c
- [ ] Line 1176: if(Py_CHECKWRITE(v)){ - [ ] Line 1193: if(Py_CHECKWRITE(v)){ - [x] Line 1639: if(!Py_CHECKWRITE(obj)){ The first two cases are in `PyObject_SetAttr`. I believe that `PyObject_SetAttr` falls out for free with the default `tp_setattro` implementation which simply calls `PyObjectGenericSetAttr` which in turn always ends up in `dictobject.c` -- unless we hit line 1567 which uses `tp_descr_set`, overloading of `__set__`. However, `__set__` descriptors' behaviour should fall out for free as they will eventually hit a "normal" store which should be trapped by the write barrier. The normal `tp_setattro` implementation is changed by `__setattr__` being overridden by user. We should expect things to fall out for free in this case since that code will eventually hit a "normal" store. Exceptions: unless the implementation of `__setattr__` or `__set__` is written in C. **Question: how to handle this case?** The third and last case is a call to `PyObject_GenericSetDict` which is the setter for `o.__dict__ = v`. In this case, we need an add ref on the v and a remove ref on the old value of `o.__dict__`. This has been implemented. However, I have so far been unable to trigger this code. `o.__dict__ = v` runs `subtype_setdict` which I have extended in a similar fashion. I have potentially discovered a couple of places missing a CHECKWRITE which I will report on in an issue.
1 parent 338f19e commit b47926d

File tree

4 files changed

+25
-4
lines changed

4 files changed

+25
-4
lines changed

Include/internal/pycore_regions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ PyObject* _Py_ResetInvariant(void);
3939
#define Py_ResetInvariant() _Py_ResetInvariant()
4040

4141
// Invariant placeholder
42+
bool _Pyrona_RemoveReference(PyObject* target, PyObject* old_ref);
43+
#define Pyrona_REMOVEREFERENCE(a, b) _Pyrona_RemoveReference(a, b)
4244
bool _Pyrona_AddReference(PyObject* target, PyObject* new_ref);
4345
#define Pyrona_ADDREFERENCE(a, b) _Pyrona_AddReference(a, b)
4446
// Helper macros to count the number of arguments

Objects/object.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1667,8 +1667,12 @@ PyObject_GenericSetDict(PyObject *obj, PyObject *value, void *context)
16671667
"not a '%.200s'", Py_TYPE(value)->tp_name);
16681668
return -1;
16691669
}
1670-
Py_XSETREF(*dictptr, Py_NewRef(value));
1671-
return 0;
1670+
if (_Pyrona_AddReference(obj, value)) {
1671+
Py_XSETREF(*dictptr, Py_NewRef(value));
1672+
return 0;
1673+
} else {
1674+
return -1;
1675+
}
16721676
}
16731677

16741678

Objects/regions.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,6 +1297,13 @@ static const char *get_region_name(PyObject* obj) {
12971297
}
12981298

12991299
// TODO replace with write barrier code
1300+
bool _Pyrona_RemoveReference(PyObject *tgt, PyObject *old_ref) {
1301+
#ifndef NDEBUG
1302+
_Py_VPYDBG("Removed %p --> %p (owner: '%s')\n", tgt, old_ref, get_region_name(tgt));
1303+
#endif
1304+
return true; // TODO: implement
1305+
}
1306+
13001307
bool _Pyrona_AddReference(PyObject *tgt, PyObject *new_ref) {
13011308
if (Py_REGION(tgt) == Py_REGION(new_ref)) {
13021309
// Nothing to do -- intra-region references are always permitted

Objects/typeobject.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "Python.h"
44
#include "pycore_call.h"
55
#include "pycore_code.h" // CO_FAST_FREE
6+
#include "pycore_regions.h"
67
#include "pycore_symtable.h" // _Py_Mangle()
78
#include "pycore_dict.h" // _PyDict_KeysSize()
89
#include "pycore_initconfig.h" // _PyStatus_OK()
@@ -2940,8 +2941,15 @@ subtype_setdict(PyObject *obj, PyObject *value, void *context)
29402941
"not a '%.200s'", Py_TYPE(value)->tp_name);
29412942
return -1;
29422943
}
2943-
Py_XSETREF(*dictptr, Py_XNewRef(value));
2944-
return 0;
2944+
if (_Pyrona_AddReference(obj, value)) {
2945+
if (*dictptr) {
2946+
_Pyrona_RemoveReference(obj, *dictptr);
2947+
}
2948+
Py_XSETREF(*dictptr, Py_XNewRef(value));
2949+
return 0;
2950+
} else {
2951+
return -1;
2952+
}
29452953
}
29462954

29472955
static PyObject *

0 commit comments

Comments
 (0)