File: pmethodobject.c

package info (click to toggle)
psyco 1.5.1-3
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 1,864 kB
  • ctags: 3,295
  • sloc: ansic: 24,491; python: 5,573; perl: 1,309; makefile: 166; sh: 1
file content (154 lines) | stat: -rw-r--r-- 3,954 bytes parent folder | download | duplicates (3)
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);
}