1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
#include "pmethodobject.h"
#include "ptupleobject.h"
static bool compute_cfunction(PsycoObject* po, vinfo_t* methobj)
{
vinfo_t* newobj;
vinfo_t* m_self;
vinfo_t* m_ml;
/* get the fields from the Python object 'methobj' */
m_self = vinfo_getitem(methobj, iCFUNC_M_SELF);
if (m_self == NULL)
return false;
m_ml = vinfo_getitem(methobj, iCFUNC_M_ML);
if (m_ml == NULL)
return false;
/* call PyCFunction_New() */
#ifdef PyCFunction_New /* Python >= 2.3 introduced PyCFunction_NewEx() */
newobj = psyco_generic_call(po, PyCFunction_NewEx,
CfPure|CfReturnRef|CfPyErrIfNull,
"vvl", m_ml, m_self, NULL);
#else
newobj = psyco_generic_call(po, PyCFunction_New,
CfPure|CfReturnRef|CfPyErrIfNull,
"vv", m_ml, m_self);
#endif
if (newobj == NULL)
return false;
/* move the resulting non-virtual Python object back into 'methobj' */
vinfo_move(po, methobj, newobj);
return true;
}
static PyObject* direct_compute_cfunction(vinfo_t* methobj, char* data)
{
PyObject* m_self;
long m_ml;
PyObject* result = NULL;
m_self = direct_xobj_vinfo(
vinfo_getitem(methobj, iCFUNC_M_SELF), data);
m_ml = direct_read_vinfo(
vinfo_getitem(methobj, iCFUNC_M_ML), data);
if (!PyErr_Occurred())
result = PyCFunction_New((PyMethodDef*) m_ml, m_self);
Py_XDECREF(m_self);
return result;
}
DEFINEVAR source_virtual_t psyco_computed_cfunction;
/***************************************************************/
/*** C method objects meta-implementation ***/
DEFINEFN
vinfo_t* PsycoCFunction_Call(PsycoObject* po, vinfo_t* func,
vinfo_t* tuple, vinfo_t* kw)
{
long mllong;
vinfo_t* vml = psyco_get_const(po, func, CFUNC_m_ml);
if (vml == NULL)
return NULL;
/* promote to compile-time the function if we do not know which one
it is yet */
mllong = psyco_atcompiletime(po, vml);
if (mllong == -1) {
/* -1 is not a valid pointer */
extra_assert(PycException_Occurred(po));
return NULL;
}
else {
PyMethodDef* ml = (PyMethodDef*) \
CompileTime_Get(vml->source)->value;
int flags = ml->ml_flags;
int tuplesize;
vinfo_t* carg;
char* argumentlist = "vv";
vinfo_t* vself = psyco_get_const(po, func, CFUNC_m_self);
if (vself == NULL)
return NULL;
if (flags & METH_KEYWORDS) {
return Psyco_META3(po, ml->ml_meth,
CfReturnRef|CfPyErrIfNull,
"vvv", vself, tuple, kw);
}
if (!psyco_knowntobe(kw, (long) NULL))
goto use_proxy;
switch (flags) {
case METH_VARARGS:
carg = tuple;
break;
#if HAVE_METH_NOARGS
case METH_NOARGS:
tuplesize = PsycoTuple_Load(tuple);
if (tuplesize != 0)
/* if size unknown or known to be != 0 */
goto use_proxy;
carg = NULL;
argumentlist = "vl";
break;
#endif
#if HAVE_METH_O
case METH_O:
tuplesize = PsycoTuple_Load(tuple);
if (tuplesize != 1)
/* if size unknown or known to be != 1 */
goto use_proxy;
carg = PsycoTuple_GET_ITEM(tuple, 0);
break;
#endif
default:
goto use_proxy;
}
return Psyco_META2(po, ml->ml_meth, CfReturnRef|CfPyErrIfNull,
argumentlist, vself, carg);
}
/* default, slow version */
use_proxy:
#if NEW_STYLE_TYPES /* Python >= 2.2b1 */
return psyco_generic_call(po, PyCFunction_Call,
CfReturnRef|CfPyErrIfNull,
"vvv", func, tuple, kw);
#else
/* no PyCFunction_Call() */
return psyco_generic_call(po, PyEval_CallObjectWithKeywords,
CfReturnRef|CfPyErrIfNull,
"vvv", func, tuple, kw);
#endif
}
INITIALIZATIONFN
void psy_methodobject_init(void)
{
#if NEW_STYLE_TYPES /* Python >= 2.2b1 */
Psyco_DefineMeta(PyCFunction_Type.tp_call, PsycoCFunction_Call);
#endif
INIT_SVIRTUAL(psyco_computed_cfunction, compute_cfunction,
direct_compute_cfunction,
(1 << iCFUNC_M_SELF),
1, 1);
}
|