mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-11 08:03:55 +00:00
Only allocate dict pointer when needed for dynamic attributes
This commit is contained in:
parent
6fccf69360
commit
22726c9d22
@ -297,7 +297,6 @@ inline std::string error_string();
|
||||
template <typename type> struct instance_essentials {
|
||||
PyObject_HEAD
|
||||
type *value;
|
||||
PyObject *dict;
|
||||
PyObject *weakrefs;
|
||||
bool owned : 1;
|
||||
bool constructed : 1;
|
||||
|
@ -574,24 +574,24 @@ public:
|
||||
|
||||
NAMESPACE_BEGIN(detail)
|
||||
extern "C" inline PyObject *get_dict(PyObject *op, void *) {
|
||||
auto *self = (instance<void> *) op;
|
||||
if (!self->dict) {
|
||||
self->dict = PyDict_New();
|
||||
PyObject *&dict = *_PyObject_GetDictPtr(op);
|
||||
if (!dict) {
|
||||
dict = PyDict_New();
|
||||
}
|
||||
Py_XINCREF(self->dict);
|
||||
return self->dict;
|
||||
Py_XINCREF(dict);
|
||||
return dict;
|
||||
}
|
||||
|
||||
extern "C" inline int set_dict(PyObject *op, PyObject *dict, void *) {
|
||||
if (!PyDict_Check(dict)) {
|
||||
extern "C" inline int set_dict(PyObject *op, PyObject *new_dict, void *) {
|
||||
if (!PyDict_Check(new_dict)) {
|
||||
PyErr_Format(PyExc_TypeError, "__dict__ must be set to a dictionary, not a '%.200s'",
|
||||
Py_TYPE(dict)->tp_name);
|
||||
Py_TYPE(new_dict)->tp_name);
|
||||
return -1;
|
||||
}
|
||||
auto *self = (instance<void> *) op;
|
||||
Py_INCREF(dict);
|
||||
Py_CLEAR(self->dict);
|
||||
self->dict = dict;
|
||||
PyObject *&dict = *_PyObject_GetDictPtr(op);
|
||||
Py_INCREF(new_dict);
|
||||
Py_CLEAR(dict);
|
||||
dict = new_dict;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -714,7 +714,8 @@ protected:
|
||||
/* Support dynamic attributes */
|
||||
if (rec->dynamic_attr) {
|
||||
type->ht_type.tp_flags |= Py_TPFLAGS_HAVE_GC;
|
||||
type->ht_type.tp_dictoffset = offsetof(instance_essentials<void>, dict);
|
||||
type->ht_type.tp_dictoffset = type->ht_type.tp_basicsize; // place the dict at the end
|
||||
type->ht_type.tp_basicsize += sizeof(PyObject *); // and allocate enough space for it
|
||||
type->ht_type.tp_getset = generic_getset;
|
||||
type->ht_type.tp_traverse = traverse;
|
||||
type->ht_type.tp_clear = clear;
|
||||
@ -822,20 +823,23 @@ protected:
|
||||
if (self->weakrefs)
|
||||
PyObject_ClearWeakRefs((PyObject *) self);
|
||||
|
||||
Py_CLEAR(self->dict);
|
||||
PyObject **dict_ptr = _PyObject_GetDictPtr((PyObject *) self);
|
||||
if (dict_ptr) {
|
||||
Py_CLEAR(*dict_ptr);
|
||||
}
|
||||
}
|
||||
Py_TYPE(self)->tp_free((PyObject*) self);
|
||||
}
|
||||
|
||||
static int traverse(PyObject *op, visitproc visit, void *arg) {
|
||||
auto *self = (instance<void> *) op;
|
||||
Py_VISIT(self->dict);
|
||||
PyObject *&dict = *_PyObject_GetDictPtr(op);
|
||||
Py_VISIT(dict);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clear(PyObject *op) {
|
||||
auto *self = (instance<void> *) op;
|
||||
Py_CLEAR(self->dict);
|
||||
PyObject *&dict = *_PyObject_GetDictPtr(op);
|
||||
Py_CLEAR(dict);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user