File: pmethodobject.c

package info (click to toggle)
psyco 1.6-1
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 1,824 kB
  • ctags: 3,237
  • sloc: ansic: 23,895; python: 5,646; perl: 1,309; makefile: 165; sh: 1
file content (141 lines) | stat: -rw-r--r-- 3,570 bytes parent folder | download | duplicates (4)
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
#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;
		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;
		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;
		default:
			goto use_proxy;
		}
		return Psyco_META2(po, ml->ml_meth, CfReturnRef|CfPyErrIfNull,
				   argumentlist, vself, carg);
	}

	/* default, slow version */
   use_proxy:
	return psyco_generic_call(po, PyCFunction_Call,
				  CfReturnRef|CfPyErrIfNull,
				  "vvv", func, tuple, kw);
}


INITIALIZATIONFN
void psy_methodobject_init(void)
{
	Psyco_DefineMeta(PyCFunction_Type.tp_call, PsycoCFunction_Call);
        INIT_SVIRTUAL(psyco_computed_cfunction, compute_cfunction,
		      direct_compute_cfunction,
                      (1 << iCFUNC_M_SELF),
                      1, 1);
}