61
61
static void _write_to_ref_info(struct ref_info *info, const char *fmt_string, ...);
63
static PyObject * _get_specials();
64
65
/* The address of the last thing we dumped. Stuff like dumping the string
65
66
* interned dictionary will dump the same string 2x in a row. This helps
68
69
static PyObject *_last_dumped = NULL;
70
static PyObject *_special_case_dict = NULL;
71
73
_clear_last_dumped()
99
101
+ num_entries * c_obj->ob_type->tp_itemsize;
105
_object_to_size_with_gc(PyObject *size_obj, PyObject *c_obj)
107
Py_ssize_t size = -1;
109
size = PyInt_AsSsize_t(size_obj);
111
// Probably an error occurred, we don't know for sure, but we might as
112
// well just claim that we don't know the size. We *could* check
113
// PyErr_Occurred(), but if we are just clearing it anyway...
117
// There is one trick left. Namely, __sizeof__ doesn't include the
118
// GC overhead, so let's add that back in
119
if (PyType_HasFeature(Py_TYPE(c_obj), Py_TPFLAGS_HAVE_GC)) {
120
size += sizeof(PyGC_Head);
103
126
_size_of_from__sizeof__(PyObject *c_obj)
105
128
PyObject *size_obj = NULL;
120
size = PyInt_AsSsize_t(size_obj);
122
// Probably an error occurred, we don't know for sure, but we might as
123
// well just claim that we don't know the size. We *could* check
124
// PyErr_Occurred(), but if we are just clearing it anyway...
128
// There is one trick left. Namely, __sizeof__ doesn't seem to include the
129
// GC overhead, so let's add that back in
130
if (PyType_HasFeature(c_obj->ob_type, Py_TPFLAGS_HAVE_GC)) {
131
size += sizeof(PyGC_Head);
143
size = _object_to_size_with_gc(size_obj, c_obj);
138
150
_size_of_list(PyListObject *c_obj)
193
_size_of_from_specials(PyObject *c_obj)
195
PyObject *special_dict;
196
PyObject *special_size_of;
200
special_dict = _get_specials();
201
if (special_dict == NULL) {
202
PyErr_Clear(); // Not sure what happened, but don't propogate it
205
special_size_of = PyDict_GetItemString(special_dict,
206
Py_TYPE(c_obj)->tp_name);
207
if (special_size_of == NULL) {
208
// if special_size_of is NULL, an exception is *not* set
211
// special_size_of is a *borrowed referenced*
212
val = PyObject_CallFunction(special_size_of, "O", c_obj);
216
size = _object_to_size_with_gc(val, c_obj);
222
_size_of_from_var_or_basic_size(PyObject *c_obj)
224
/* There are a bunch of types that we know we can check directly, without
225
* having to go through the __sizeof__ abstraction. This allows us to avoid
226
* the extra intermediate allocations. It is also our final fallback
230
if (c_obj->ob_type->tp_itemsize != 0) {
231
// Variable length object with inline storage
232
// total size is tp_itemsize * ob_size
233
return _var_object_size((PyVarObject *)c_obj);
235
return _basic_object_size(c_obj);
182
239
_size_of(PyObject *c_obj)
191
248
return _size_of_dict((PyDictObject *)c_obj);
192
249
} else if PyUnicode_Check(c_obj) {
193
250
return _size_of_unicode((PyUnicodeObject *)c_obj);
251
} else if (PyTuple_CheckExact(c_obj)
252
|| PyString_CheckExact(c_obj)
253
|| PyInt_CheckExact(c_obj)
254
|| PyBool_Check(c_obj)
256
|| PyModule_CheckExact(c_obj))
258
// All of these implement __sizeof__, but we don't need to use it
259
return _size_of_from_var_or_basic_size(c_obj);
262
// object implements __sizeof__ so we have to specials first
263
size = _size_of_from_specials(c_obj);
196
267
size = _size_of_from__sizeof__(c_obj);
197
268
if (size != -1) {
201
if (c_obj->ob_type->tp_itemsize != 0) {
202
// Variable length object with inline storage
203
// total size is tp_itemsize * ob_size
204
return _var_object_size((PyVarObject *)c_obj);
206
return _basic_object_size(c_obj);
271
return _size_of_from_var_or_basic_size(c_obj);