Skip to content

Commit

Permalink
C part of 'byprod' producer classifier
Browse files Browse the repository at this point in the history
Ref #11
  • Loading branch information
zhuyifei1999 committed Nov 12, 2019
1 parent 17c9c27 commit 4e12169
Show file tree
Hide file tree
Showing 4 changed files with 208 additions and 52 deletions.
1 change: 1 addition & 0 deletions src/heapy/hv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1758,6 +1758,7 @@ static PyMethodDef hv_methods[] = {
{"cli_indisize", (PyCFunction)hv_cli_indisize, METH_VARARGS, hv_cli_indisize_doc},
{"cli_inrel", (PyCFunction)hv_cli_inrel, METH_VARARGS, hv_cli_inrel_doc},
{"cli_none", (PyCFunction)hv_cli_none, METH_NOARGS, hv_cli_none_doc},
{"cli_prod", (PyCFunction)hv_cli_prod, METH_VARARGS, hv_cli_prod_doc},
{"cli_rcs", (PyCFunction)hv_cli_rcs, METH_VARARGS, hv_cli_rcs_doc},
{"cli_type", (PyCFunction)hv_cli_type, METH_NOARGS, hv_cli_type_doc},
{"cli_user_defined", (PyCFunction)hv_cli_user_defined, METH_VARARGS|METH_KEYWORDS, hv_cli_user_defined_doc},
Expand Down
1 change: 1 addition & 0 deletions src/heapy/hv_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "hv_cli_dictof.c"
#include "hv_cli_id.c"
#include "hv_cli_idset.c"
#include "hv_cli_prod.c"
#include "hv_cli_rcs.c"
#include "hv_cli_indisize.c"
#include "hv_cli_findex.c"
Expand Down
159 changes: 159 additions & 0 deletions src/heapy/hv_cli_prod.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/* Implementation of the 'prod' classifier */

PyDoc_STRVAR(hv_cli_prod_doc,
"HV.cli_prod(memo) -> ObjectClassifier\n"
"\n"
"Return a classifier that classifes by \"producer\".\n"
"\n"
"The classification of an object is the fine name and line number\n"
"in which the object is produced (allocated).\n"
"\n"
" memo A dict object used to\n"
" memoize the classification sets.\n"
);

// The sizeof of PyGC_Head is not to be trusted upon even across Python minor
// released. Eg: python/cpython@8766cb7
static Py_ssize_t sizeof_PyGC_Head;

static void lazy_init_hv_cli_prod()
{
if (sizeof_PyGC_Head)
return;

if (PyLong_AsLong(PySys_GetObject("hexversion")) == PY_VERSION_HEX) {
sizeof_PyGC_Head = sizeof(PyGC_Head);
return;
}

PyObject *_testcapimodule, *_testcapi_SIZEOF_PYGC_HEAD = NULL;

_testcapimodule = PyImport_ImportModule("_testcapi");
if (!_testcapimodule)
goto Err;

_testcapi_SIZEOF_PYGC_HEAD = PyObject_GetAttrString(
_testcapimodule, "SIZEOF_PYGC_HEAD");
if (!_testcapi_SIZEOF_PYGC_HEAD)
goto Err;

sizeof_PyGC_Head = PyLong_AsSsize_t(_testcapi_SIZEOF_PYGC_HEAD);
if (sizeof_PyGC_Head < 0)
goto Err;

Py_DECREF(_testcapimodule);
Py_DECREF(_testcapi_SIZEOF_PYGC_HEAD);
return;

Err:
Py_XDECREF(_testcapimodule);
Py_XDECREF(_testcapi_SIZEOF_PYGC_HEAD);

PyErr_Clear();
sizeof_PyGC_Head = sizeof(PyGC_Head);
PyErr_WarnFormat(PyExc_UserWarning, 1,
"Unable to determine sizeof(PyGC_Head) from "
"_testcapi.SIZEOF_PYGC_HEAD, assuming %zd",
sizeof_PyGC_Head);
}

typedef struct {
PyObject_VAR_HEAD
NyHeapViewObject *hv;
PyObject *memo;
} ProdObject;

static PyObject *
hv_cli_prod_memoized_kind(ProdObject * self, PyObject *kind)
{
PyObject *result = PyDict_GetItem(self->memo, kind);
if (!result) {
if (PyErr_Occurred())
goto Err;
if (PyDict_SetItem(self->memo, kind, kind) == -1)
goto Err;
result = kind;
}
Py_INCREF(result);
return result;
Err:
return 0;
}

static PyObject *
hv_cli_prod_classify(ProdObject *self, PyObject *obj)
{
Py_uintptr_t ptr;
PyTypeObject *type;
PyObject *kind = NULL;
PyObject *tb, *result;

// Refer to _tracemalloc.c:_tracemalloc__get_object_traceback
type = Py_TYPE(obj);
if (PyType_IS_GC(type)) {
ptr = (Py_uintptr_t)((char *)obj - sizeof_PyGC_Head);
} else {
ptr = (Py_uintptr_t)obj;
}

tb = _PyTraceMalloc_GetTraceback(0, (Py_uintptr_t)ptr);

if (!tb)
goto Err;

if (PySequence_Check(tb) && PySequence_Length(tb)) {
kind = PySequence_GetItem(tb, 0);
} else {
kind = Py_None;
Py_INCREF(Py_None);
}

result = hv_cli_prod_memoized_kind(self, kind);
Py_DECREF(tb);
Py_DECREF(kind);
return result;

Err:
Py_XDECREF(tb);
Py_XDECREF(kind);
return 0;
}

static int
hv_cli_prod_le(PyObject * self, PyObject *a, PyObject *b)
{
return PyObject_RichCompareBool(a, b, Py_LE);
}

static NyObjectClassifierDef hv_cli_prod_def = {
0,
sizeof(NyObjectClassifierDef),
"hv_cli_prod",
"classifier returning object producer",
(binaryfunc)hv_cli_prod_classify,
(binaryfunc)hv_cli_prod_memoized_kind,
hv_cli_prod_le
};

static PyObject *
hv_cli_prod(NyHeapViewObject *self, PyObject *args)
{
PyObject *r, *memo;
ProdObject *s;
if (!PyArg_ParseTuple(args, "O!:cli_prod",
&PyDict_Type, &memo))
return NULL;

lazy_init_hv_cli_prod();

s = NYTUPLELIKE_NEW(ProdObject);
if (!s)
return 0;
s->hv = self;
Py_INCREF(s->hv);
s->memo = memo;
Py_INCREF(memo);
r = NyObjectClassifier_New((PyObject *)s, &hv_cli_prod_def);
Py_DECREF(s);
return r;
}
99 changes: 47 additions & 52 deletions src/heapy/hv_cli_rcs.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ hv_cli_rcs_fast_memoized_kind(RetclasetObject * self, PyObject *kind)
{
PyObject *result = PyDict_GetItem(self->memo, kind);
if (!result) {
if (PyErr_Occurred())
goto Err;
if (PyDict_SetItem(self->memo, kind, kind) == -1)
goto Err;
result = kind;
if (PyErr_Occurred())
goto Err;
if (PyDict_SetItem(self->memo, kind, kind) == -1)
goto Err;
result = kind;
}
Py_INCREF(result);
return result;
Err:
Err:
return 0;
}

Expand All @@ -56,10 +56,10 @@ rcs_visit_memoize_sub(PyObject *obj, MemoRcsArg *arg)
{
obj = arg->cli->def->memoized_kind(arg->cli->self, obj);
if (!obj)
return -1;
return -1;
if (NyNodeSet_setobj(arg->ns, obj) == -1) {
Py_DECREF(obj);
return -1;
Py_DECREF(obj);
return -1;
}
Py_DECREF(obj);
return 0;
Expand All @@ -69,30 +69,30 @@ static PyObject *
hv_cli_rcs_memoized_kind(RetclasetObject * self, PyObject *kind)
{
if (!NyNodeSet_Check(kind)) {
PyErr_SetString(PyExc_TypeError,
"hv_cli_rcs_memoized_kind: nodeset object (immutable) expected.");
return 0;
PyErr_SetString(PyExc_TypeError,
"hv_cli_rcs_memoized_kind: nodeset object (immutable) expected.");
return 0;
}
if (!self->cli->def->memoized_kind) {
return hv_cli_rcs_fast_memoized_kind(self, kind);
return hv_cli_rcs_fast_memoized_kind(self, kind);
} else {
MemoRcsArg arg;
PyObject *result;
arg.cli = self->cli;
arg.ns = hv_mutnodeset_new(self->hv);
if (!arg.ns)
return 0;
if (iterable_iterate(kind, (visitproc)rcs_visit_memoize_sub, &arg) == -1)
goto Err;
if (NyNodeSet_be_immutable(&arg.ns) == -1)
goto Err;
result = hv_cli_rcs_fast_memoized_kind(self, (PyObject *)arg.ns);
Ret:
Py_DECREF(arg.ns);
return result;
Err:
result = 0;
goto Ret;
MemoRcsArg arg;
PyObject *result;
arg.cli = self->cli;
arg.ns = hv_mutnodeset_new(self->hv);
if (!arg.ns)
return 0;
if (iterable_iterate(kind, (visitproc)rcs_visit_memoize_sub, &arg) == -1)
goto Err;
if (NyNodeSet_be_immutable(&arg.ns) == -1)
goto Err;
result = hv_cli_rcs_fast_memoized_kind(self, (PyObject *)arg.ns);
Ret:
Py_DECREF(arg.ns);
return result;
Err:
result = 0;
goto Ret;
}
}

Expand All @@ -108,25 +108,25 @@ hv_cli_rcs_classify(RetclasetObject * self, PyObject *obj)
if (!Ri)
goto Err;
if (NyNodeGraph_Region(self->rg, obj, &lo, &hi) == -1) {
goto Err;
goto Err;
}
for (cur = lo; cur < hi; cur++) {
if (cur->tgt == Py_None)
continue;
kind = self->cli->def->classify(self->cli->self, cur->tgt);
if (!kind)
goto Err;
if (NyNodeSet_setobj(Ri, kind) == -1)
goto Err;
Py_DECREF(kind);
if (cur->tgt == Py_None)
continue;
kind = self->cli->def->classify(self->cli->self, cur->tgt);
if (!kind)
goto Err;
if (NyNodeSet_setobj(Ri, kind) == -1)
goto Err;
Py_DECREF(kind);
}
if (NyNodeSet_be_immutable(&Ri) == -1)
goto Err;
kind = hv_cli_rcs_fast_memoized_kind(self, (PyObject *)Ri);
Py_DECREF(Ri);
return kind;
Err:

Err:
Py_XDECREF(kind);
Py_XDECREF(Ri);
return 0;
Expand Down Expand Up @@ -154,15 +154,15 @@ hv_cli_rcs(NyHeapViewObject *hv, PyObject *args)
{
PyObject *r;
RetclasetObject *s, tmp;
if (!PyArg_ParseTuple(args, "O!O!O!:cli_rcs",
&NyNodeGraph_Type, &tmp.rg,
&NyObjectClassifier_Type, &tmp.cli,
&PyDict_Type, &tmp.memo)) {
return 0;
if (!PyArg_ParseTuple(args, "O!O!O!:cli_rcs",
&NyNodeGraph_Type, &tmp.rg,
&NyObjectClassifier_Type, &tmp.cli,
&PyDict_Type, &tmp.memo)) {
return 0;
}
s = NYTUPLELIKE_NEW(RetclasetObject);
if (!s)
return 0;
return 0;

s->hv = hv;
Py_INCREF(hv);
Expand All @@ -176,8 +176,3 @@ hv_cli_rcs(NyHeapViewObject *hv, PyObject *args)
Py_DECREF(s);
return r;
}





0 comments on commit 4e12169

Please sign in to comment.