mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-29 00:22:00 +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 {
|
template <typename type> struct instance_essentials {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
type *value;
|
type *value;
|
||||||
PyObject *dict;
|
|
||||||
PyObject *weakrefs;
|
PyObject *weakrefs;
|
||||||
bool owned : 1;
|
bool owned : 1;
|
||||||
bool constructed : 1;
|
bool constructed : 1;
|
||||||
|
@ -574,24 +574,24 @@ public:
|
|||||||
|
|
||||||
NAMESPACE_BEGIN(detail)
|
NAMESPACE_BEGIN(detail)
|
||||||
extern "C" inline PyObject *get_dict(PyObject *op, void *) {
|
extern "C" inline PyObject *get_dict(PyObject *op, void *) {
|
||||||
auto *self = (instance<void> *) op;
|
PyObject *&dict = *_PyObject_GetDictPtr(op);
|
||||||
if (!self->dict) {
|
if (!dict) {
|
||||||
self->dict = PyDict_New();
|
dict = PyDict_New();
|
||||||
}
|
}
|
||||||
Py_XINCREF(self->dict);
|
Py_XINCREF(dict);
|
||||||
return self->dict;
|
return dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" inline int set_dict(PyObject *op, PyObject *dict, void *) {
|
extern "C" inline int set_dict(PyObject *op, PyObject *new_dict, void *) {
|
||||||
if (!PyDict_Check(dict)) {
|
if (!PyDict_Check(new_dict)) {
|
||||||
PyErr_Format(PyExc_TypeError, "__dict__ must be set to a dictionary, not a '%.200s'",
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
auto *self = (instance<void> *) op;
|
PyObject *&dict = *_PyObject_GetDictPtr(op);
|
||||||
Py_INCREF(dict);
|
Py_INCREF(new_dict);
|
||||||
Py_CLEAR(self->dict);
|
Py_CLEAR(dict);
|
||||||
self->dict = dict;
|
dict = new_dict;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -714,7 +714,8 @@ protected:
|
|||||||
/* Support dynamic attributes */
|
/* Support dynamic attributes */
|
||||||
if (rec->dynamic_attr) {
|
if (rec->dynamic_attr) {
|
||||||
type->ht_type.tp_flags |= Py_TPFLAGS_HAVE_GC;
|
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_getset = generic_getset;
|
||||||
type->ht_type.tp_traverse = traverse;
|
type->ht_type.tp_traverse = traverse;
|
||||||
type->ht_type.tp_clear = clear;
|
type->ht_type.tp_clear = clear;
|
||||||
@ -822,20 +823,23 @@ protected:
|
|||||||
if (self->weakrefs)
|
if (self->weakrefs)
|
||||||
PyObject_ClearWeakRefs((PyObject *) self);
|
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);
|
Py_TYPE(self)->tp_free((PyObject*) self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int traverse(PyObject *op, visitproc visit, void *arg) {
|
static int traverse(PyObject *op, visitproc visit, void *arg) {
|
||||||
auto *self = (instance<void> *) op;
|
PyObject *&dict = *_PyObject_GetDictPtr(op);
|
||||||
Py_VISIT(self->dict);
|
Py_VISIT(dict);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int clear(PyObject *op) {
|
static int clear(PyObject *op) {
|
||||||
auto *self = (instance<void> *) op;
|
PyObject *&dict = *_PyObject_GetDictPtr(op);
|
||||||
Py_CLEAR(self->dict);
|
Py_CLEAR(dict);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user