File: | _dispatcher.cpp |
Warning: | line 1001, column 5 PyObject ownership leak with reference count of 1 |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | #include "_pymodule.h" | |||
2 | ||||
3 | #include <cstring> | |||
4 | #include <ctime> | |||
5 | #include <cassert> | |||
6 | #include <vector> | |||
7 | ||||
8 | #include "_typeof.h" | |||
9 | #include "frameobject.h" | |||
10 | #include "core/typeconv/typeconv.hpp" | |||
11 | #include "_devicearray.h" | |||
12 | ||||
13 | /* | |||
14 | * The following call_trace and call_trace_protected functions | |||
15 | * as well as the C_TRACE macro are taken from ceval.c | |||
16 | * | |||
17 | */ | |||
18 | ||||
19 | static int | |||
20 | call_trace(Py_tracefunc func, PyObject *obj, | |||
21 | PyThreadState *tstate, PyFrameObject *frame, | |||
22 | int what, PyObject *arg) | |||
23 | { | |||
24 | int result; | |||
25 | if (tstate->tracing) | |||
26 | return 0; | |||
27 | tstate->tracing++; | |||
28 | tstate->use_tracing = 0; | |||
29 | result = func(obj, frame, what, arg); | |||
30 | tstate->use_tracing = ((tstate->c_tracefunc != NULL__null) | |||
31 | || (tstate->c_profilefunc != NULL__null)); | |||
32 | tstate->tracing--; | |||
33 | return result; | |||
34 | } | |||
35 | ||||
36 | static int | |||
37 | call_trace_protected(Py_tracefunc func, PyObject *obj, | |||
38 | PyThreadState *tstate, PyFrameObject *frame, | |||
39 | int what, PyObject *arg) | |||
40 | { | |||
41 | PyObject *type, *value, *traceback; | |||
42 | int err; | |||
43 | PyErr_Fetch(&type, &value, &traceback); | |||
44 | err = call_trace(func, obj, tstate, frame, what, arg); | |||
45 | if (err == 0) | |||
46 | { | |||
47 | PyErr_Restore(type, value, traceback); | |||
48 | return 0; | |||
49 | } | |||
50 | else | |||
51 | { | |||
52 | Py_XDECREF(type)_Py_XDECREF(((PyObject*)(type))); | |||
53 | Py_XDECREF(value)_Py_XDECREF(((PyObject*)(value))); | |||
54 | Py_XDECREF(traceback)_Py_XDECREF(((PyObject*)(traceback))); | |||
55 | return -1; | |||
56 | } | |||
57 | } | |||
58 | ||||
59 | /* | |||
60 | * The original C_TRACE macro (from ceval.c) would call | |||
61 | * PyTrace_C_CALL et al., for which the frame argument wouldn't | |||
62 | * be usable. Since we explicitly synthesize a frame using the | |||
63 | * original Python code object, we call PyTrace_CALL instead so | |||
64 | * the profiler can report the correct source location. | |||
65 | * | |||
66 | * Likewise, while ceval.c would call PyTrace_C_EXCEPTION in case | |||
67 | * of error, the profiler would simply expect a RETURN in case of | |||
68 | * a Python function, so we generate that here (making sure the | |||
69 | * exception state is preserved correctly). | |||
70 | */ | |||
71 | #define C_TRACE(x, call)if (call_trace(tstate->c_profilefunc, tstate->c_profileobj , tstate, tstate->frame, 0, cfunc)) x = __null; else { x = call; if (tstate->c_profilefunc != __null) { if (x == __null ) { call_trace_protected(tstate->c_profilefunc, tstate-> c_profileobj, tstate, tstate->frame, 3, cfunc); } else { if (call_trace(tstate->c_profilefunc, tstate->c_profileobj , tstate, tstate->frame, 3, cfunc)) { _Py_DECREF(((PyObject *)(x))); x = __null; } } } } \ | |||
72 | if (call_trace(tstate->c_profilefunc, tstate->c_profileobj, \ | |||
73 | tstate, tstate->frame, PyTrace_CALL0, cfunc)) \ | |||
74 | x = NULL__null; \ | |||
75 | else \ | |||
76 | { \ | |||
77 | x = call; \ | |||
78 | if (tstate->c_profilefunc != NULL__null) \ | |||
79 | { \ | |||
80 | if (x == NULL__null) \ | |||
81 | { \ | |||
82 | call_trace_protected(tstate->c_profilefunc, \ | |||
83 | tstate->c_profileobj, \ | |||
84 | tstate, tstate->frame, \ | |||
85 | PyTrace_RETURN3, cfunc); \ | |||
86 | /* XXX should pass (type, value, tb) */ \ | |||
87 | } \ | |||
88 | else \ | |||
89 | { \ | |||
90 | if (call_trace(tstate->c_profilefunc, \ | |||
91 | tstate->c_profileobj, \ | |||
92 | tstate, tstate->frame, \ | |||
93 | PyTrace_RETURN3, cfunc)) \ | |||
94 | { \ | |||
95 | Py_DECREF(x)_Py_DECREF(((PyObject*)(x))); \ | |||
96 | x = NULL__null; \ | |||
97 | } \ | |||
98 | } \ | |||
99 | } \ | |||
100 | } | |||
101 | ||||
102 | typedef std::vector<Type> TypeTable; | |||
103 | typedef std::vector<PyObject*> Functions; | |||
104 | ||||
105 | /* The Dispatcher class is the base class of all dispatchers in the CPU and | |||
106 | CUDA targets. Its main responsibilities are: | |||
107 | ||||
108 | - Resolving the best overload to call for a given set of arguments, and | |||
109 | - Calling the resolved overload. | |||
110 | ||||
111 | This logic is implemented within this class for efficiency (lookup of the | |||
112 | appropriate overload needs to be fast) and ease of implementation (calling | |||
113 | directly into a compiled function using a function pointer is easier within | |||
114 | the C++ code where the overload has been resolved). */ | |||
115 | class Dispatcher { | |||
116 | public: | |||
117 | PyObject_HEADPyObject ob_base; | |||
118 | /* Whether compilation of new overloads is permitted */ | |||
119 | char can_compile; | |||
120 | /* Whether fallback to object mode is permitted */ | |||
121 | char can_fallback; | |||
122 | /* Whether types must match exactly when resolving overloads. | |||
123 | If not, conversions (e.g. float32 -> float64) are permitted when | |||
124 | searching for a match. */ | |||
125 | char exact_match_required; | |||
126 | /* Borrowed reference */ | |||
127 | PyObject *fallbackdef; | |||
128 | /* Whether to fold named arguments and default values | |||
129 | (false for lifted loops) */ | |||
130 | int fold_args; | |||
131 | /* Whether the last positional argument is a stararg */ | |||
132 | int has_stararg; | |||
133 | /* Tuple of argument names */ | |||
134 | PyObject *argnames; | |||
135 | /* Tuple of default values */ | |||
136 | PyObject *defargs; | |||
137 | /* Number of arguments to function */ | |||
138 | int argct; | |||
139 | /* Used for selecting overloaded function implementations */ | |||
140 | TypeManager *tm; | |||
141 | /* An array of overloads */ | |||
142 | Functions functions; | |||
143 | /* A flattened array of argument types to all overloads | |||
144 | * (invariant: sizeof(overloads) == argct * sizeof(functions)) */ | |||
145 | TypeTable overloads; | |||
146 | ||||
147 | /* Add a new overload. Parameters: | |||
148 | ||||
149 | - args: An array of Type objects, one for each parameter | |||
150 | - callable: The callable implementing this overload. */ | |||
151 | void addDefinition(Type args[], PyObject *callable) { | |||
152 | overloads.reserve(argct + overloads.size()); | |||
153 | for (int i=0; i<argct; ++i) { | |||
154 | overloads.push_back(args[i]); | |||
155 | } | |||
156 | functions.push_back(callable); | |||
157 | } | |||
158 | ||||
159 | /* Given a list of types, find the overloads that have a matching signature. | |||
160 | Returns the best match, as well as the number of matches found. | |||
161 | ||||
162 | Parameters: | |||
163 | ||||
164 | - sig: an array of Type objects, one for each parameter. | |||
165 | - matches: the number of matches found (mutated by this function). | |||
166 | - allow_unsafe: whether to match overloads that would require an unsafe | |||
167 | cast. | |||
168 | - exact_match_required: Whether all arguments types must match the | |||
169 | overload's types exactly. When false, | |||
170 | overloads that would require a type conversion | |||
171 | can also be matched. */ | |||
172 | PyObject* resolve(Type sig[], int &matches, bool allow_unsafe, | |||
173 | bool exact_match_required) const { | |||
174 | const int ovct = functions.size(); | |||
175 | int selected; | |||
176 | matches = 0; | |||
177 | if (0 == ovct) { | |||
178 | // No overloads registered | |||
179 | return NULL__null; | |||
180 | } | |||
181 | if (argct == 0) { | |||
182 | // Nullary function: trivial match on first overload | |||
183 | matches = 1; | |||
184 | selected = 0; | |||
185 | } | |||
186 | else { | |||
187 | matches = tm->selectOverload(sig, &overloads[0], selected, argct, | |||
188 | ovct, allow_unsafe, | |||
189 | exact_match_required); | |||
190 | } | |||
191 | if (matches == 1) { | |||
192 | return functions[selected]; | |||
193 | } | |||
194 | return NULL__null; | |||
195 | } | |||
196 | ||||
197 | /* Remove all overloads */ | |||
198 | void clear() { | |||
199 | functions.clear(); | |||
200 | overloads.clear(); | |||
201 | } | |||
202 | ||||
203 | }; | |||
204 | ||||
205 | ||||
206 | static int | |||
207 | Dispatcher_traverse(Dispatcher *self, visitproc visit, void *arg) | |||
208 | { | |||
209 | Py_VISIT(self->defargs)do { if (self->defargs) { int vret = visit(((PyObject*)(self ->defargs)), arg); if (vret) return vret; } } while (0); | |||
210 | return 0; | |||
211 | } | |||
212 | ||||
213 | static void | |||
214 | Dispatcher_dealloc(Dispatcher *self) | |||
215 | { | |||
216 | Py_XDECREF(self->argnames)_Py_XDECREF(((PyObject*)(self->argnames))); | |||
217 | Py_XDECREF(self->defargs)_Py_XDECREF(((PyObject*)(self->defargs))); | |||
218 | self->clear(); | |||
219 | Py_TYPE(self)(((PyObject*)(self))->ob_type)->tp_free((PyObject*)self); | |||
220 | } | |||
221 | ||||
222 | ||||
223 | static int | |||
224 | Dispatcher_init(Dispatcher *self, PyObject *args, PyObject *kwds) | |||
225 | { | |||
226 | PyObject *tmaddrobj; | |||
227 | void *tmaddr; | |||
228 | int argct; | |||
229 | int can_fallback; | |||
230 | int has_stararg = 0; | |||
231 | int exact_match_required = 0; | |||
232 | ||||
233 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "OiiO!O!i|ii", &tmaddrobj, &argct, | |||
234 | &self->fold_args, | |||
235 | &PyTuple_Type, &self->argnames, | |||
236 | &PyTuple_Type, &self->defargs, | |||
237 | &can_fallback, | |||
238 | &has_stararg, | |||
239 | &exact_match_required | |||
240 | )) { | |||
241 | return -1; | |||
242 | } | |||
243 | Py_INCREF(self->argnames)_Py_INCREF(((PyObject*)(self->argnames))); | |||
244 | Py_INCREF(self->defargs)_Py_INCREF(((PyObject*)(self->defargs))); | |||
245 | tmaddr = PyLong_AsVoidPtr(tmaddrobj); | |||
246 | self->tm = static_cast<TypeManager*>(tmaddr); | |||
247 | self->argct = argct; | |||
248 | self->can_compile = 1; | |||
249 | self->can_fallback = can_fallback; | |||
250 | self->fallbackdef = NULL__null; | |||
251 | self->has_stararg = has_stararg; | |||
252 | self->exact_match_required = exact_match_required; | |||
253 | return 0; | |||
254 | } | |||
255 | ||||
256 | static PyObject * | |||
257 | Dispatcher_clear(Dispatcher *self, PyObject *args) | |||
258 | { | |||
259 | self->clear(); | |||
260 | Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (& _Py_NoneStruct); | |||
261 | } | |||
262 | ||||
263 | static | |||
264 | PyObject* | |||
265 | Dispatcher_Insert(Dispatcher *self, PyObject *args, PyObject *kwds) | |||
266 | { | |||
267 | /* The cuda kwarg is a temporary addition until CUDA overloads are compiled | |||
268 | * functions. Once they are compiled functions, kwargs can be removed from | |||
269 | * this function. */ | |||
270 | static char *keywords[] = { | |||
271 | (char*)"sig", | |||
272 | (char*)"func", | |||
273 | (char*)"objectmode", | |||
274 | (char*)"cuda", | |||
275 | NULL__null | |||
276 | }; | |||
277 | ||||
278 | PyObject *sigtup, *cfunc; | |||
279 | int i, sigsz; | |||
280 | int *sig; | |||
281 | int objectmode = 0; | |||
282 | int cuda = 0; | |||
283 | ||||
284 | if (!PyArg_ParseTupleAndKeywords_PyArg_ParseTupleAndKeywords_SizeT(args, kwds, "OO|ip", keywords, &sigtup, | |||
285 | &cfunc, &objectmode, &cuda)) { | |||
286 | return NULL__null; | |||
287 | } | |||
288 | ||||
289 | if (!cuda && !PyObject_TypeCheck(cfunc, &PyCFunction_Type)((((PyObject*)(cfunc))->ob_type) == (&PyCFunction_Type ) || PyType_IsSubtype((((PyObject*)(cfunc))->ob_type), (& PyCFunction_Type))) ) { | |||
290 | PyErr_SetString(PyExc_TypeError, "must be builtin_function_or_method"); | |||
291 | return NULL__null; | |||
292 | } | |||
293 | ||||
294 | sigsz = PySequence_Fast_GET_SIZE(sigtup)(((((((PyObject*)(sigtup))->ob_type))->tp_flags & ( (1UL << 25))) != 0) ? ((static_cast<void> (0)), ( ((PyVarObject*)(sigtup))->ob_size)) : (((PyVarObject*)(((static_cast <void> (0)), (PyTupleObject *)(sigtup))))->ob_size)); | |||
295 | sig = new int[sigsz]; | |||
296 | ||||
297 | for (i = 0; i < sigsz; ++i) { | |||
298 | sig[i] = PyLong_AsLong(PySequence_Fast_GET_ITEM(sigtup, i)(((((((PyObject*)(sigtup))->ob_type))->tp_flags & ( (1UL << 25))) != 0) ? (((PyListObject *)(sigtup))->ob_item [i]) : (((static_cast<void> (0)), (PyTupleObject *)(sigtup ))->ob_item[i]))); | |||
299 | } | |||
300 | ||||
301 | /* The reference to cfunc is borrowed; this only works because the | |||
302 | derived Python class also stores an (owned) reference to cfunc. */ | |||
303 | self->addDefinition(sig, cfunc); | |||
304 | ||||
305 | /* Add pure python fallback */ | |||
306 | if (!self->fallbackdef && objectmode){ | |||
307 | self->fallbackdef = cfunc; | |||
308 | } | |||
309 | ||||
310 | delete[] sig; | |||
311 | ||||
312 | Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (& _Py_NoneStruct); | |||
313 | } | |||
314 | ||||
315 | static | |||
316 | void explain_issue(PyObject *dispatcher, PyObject *args, PyObject *kws, | |||
317 | const char *method_name, const char *default_msg) | |||
318 | { | |||
319 | PyObject *callback, *result; | |||
320 | callback = PyObject_GetAttrString(dispatcher, method_name); | |||
321 | if (!callback) { | |||
322 | PyErr_SetString(PyExc_TypeError, default_msg); | |||
323 | return; | |||
324 | } | |||
325 | result = PyObject_Call(callback, args, kws); | |||
326 | Py_DECREF(callback)_Py_DECREF(((PyObject*)(callback))); | |||
327 | if (result != NULL__null) { | |||
328 | PyErr_Format(PyExc_RuntimeError, "%s must raise an exception", | |||
329 | method_name); | |||
330 | Py_DECREF(result)_Py_DECREF(((PyObject*)(result))); | |||
331 | } | |||
332 | } | |||
333 | ||||
334 | static | |||
335 | void explain_ambiguous(PyObject *dispatcher, PyObject *args, PyObject *kws) | |||
336 | { | |||
337 | explain_issue(dispatcher, args, kws, "_explain_ambiguous", | |||
338 | "Ambiguous overloading"); | |||
339 | } | |||
340 | ||||
341 | static | |||
342 | void explain_matching_error(PyObject *dispatcher, PyObject *args, PyObject *kws) | |||
343 | { | |||
344 | explain_issue(dispatcher, args, kws, "_explain_matching_error", | |||
345 | "No matching definition"); | |||
346 | } | |||
347 | ||||
348 | static | |||
349 | int search_new_conversions(PyObject *dispatcher, PyObject *args, PyObject *kws) | |||
350 | { | |||
351 | PyObject *callback, *result; | |||
352 | int res; | |||
353 | ||||
354 | callback = PyObject_GetAttrString(dispatcher, | |||
355 | "_search_new_conversions"); | |||
356 | if (!callback) { | |||
357 | return -1; | |||
358 | } | |||
359 | result = PyObject_Call(callback, args, kws); | |||
360 | Py_DECREF(callback)_Py_DECREF(((PyObject*)(callback))); | |||
361 | if (result == NULL__null) { | |||
362 | return -1; | |||
363 | } | |||
364 | if (!PyBool_Check(result)((((PyObject*)(result))->ob_type) == &PyBool_Type)) { | |||
365 | Py_DECREF(result)_Py_DECREF(((PyObject*)(result))); | |||
366 | PyErr_SetString(PyExc_TypeError, | |||
367 | "_search_new_conversions() should return a boolean"); | |||
368 | return -1; | |||
369 | } | |||
370 | res = (result == Py_True((PyObject *) &_Py_TrueStruct)) ? 1 : 0; | |||
371 | Py_DECREF(result)_Py_DECREF(((PyObject*)(result))); | |||
372 | return res; | |||
373 | } | |||
374 | ||||
375 | /* A custom, fast, inlinable version of PyCFunction_Call() */ | |||
376 | static PyObject * | |||
377 | call_cfunc(Dispatcher *self, PyObject *cfunc, PyObject *args, PyObject *kws, PyObject *locals) | |||
378 | { | |||
379 | PyCFunctionWithKeywords fn; | |||
380 | PyThreadState *tstate; | |||
381 | ||||
382 | assert(PyCFunction_Check(cfunc))(static_cast<void> (0)); | |||
383 | assert(PyCFunction_GET_FLAGS(cfunc) == METH_VARARGS | METH_KEYWORDS)(static_cast<void> (0)); | |||
384 | fn = (PyCFunctionWithKeywords) PyCFunction_GET_FUNCTION(cfunc)(((PyCFunctionObject *)cfunc) -> m_ml -> ml_meth); | |||
385 | tstate = PyThreadState_GET()PyThreadState_Get(); | |||
386 | ||||
387 | if (tstate->use_tracing && tstate->c_profilefunc) | |||
388 | { | |||
389 | /* | |||
390 | * The following code requires some explaining: | |||
391 | * | |||
392 | * We want the jit-compiled function to be visible to the profiler, so we | |||
393 | * need to synthesize a frame for it. | |||
394 | * The PyFrame_New() constructor doesn't do anything with the 'locals' value if the 'code's | |||
395 | * 'CO_NEWLOCALS' flag is set (which is always the case nowadays). | |||
396 | * So, to get local variables into the frame, we have to manually set the 'f_locals' | |||
397 | * member, then call `PyFrame_LocalsToFast`, where a subsequent call to the `frame.f_locals` | |||
398 | * property (by virtue of the `frame_getlocals` function in frameobject.c) will find them. | |||
399 | */ | |||
400 | PyCodeObject *code = (PyCodeObject*)PyObject_GetAttrString((PyObject*)self, "__code__"); | |||
401 | PyObject *globals = PyDict_New(); | |||
402 | PyObject *builtins = PyEval_GetBuiltins(); | |||
403 | PyFrameObject *frame = NULL__null; | |||
404 | PyObject *result = NULL__null; | |||
405 | ||||
406 | if (!code) { | |||
407 | PyErr_Format(PyExc_RuntimeError, "No __code__ attribute found."); | |||
408 | goto error; | |||
409 | } | |||
410 | /* Populate builtins, which is required by some JITted functions */ | |||
411 | if (PyDict_SetItemString(globals, "__builtins__", builtins)) { | |||
412 | goto error; | |||
413 | } | |||
414 | ||||
415 | /* unset the CO_OPTIMIZED flag, make the frame get a new locals dict */ | |||
416 | code->co_flags &= 0xFFFE; | |||
417 | ||||
418 | frame = PyFrame_New(tstate, code, globals, locals); | |||
419 | if (frame == NULL__null) { | |||
420 | goto error; | |||
421 | } | |||
422 | /* Populate the 'fast locals' in `frame` */ | |||
423 | PyFrame_LocalsToFast(frame, 0); | |||
424 | tstate->frame = frame; | |||
425 | C_TRACE(result, fn(PyCFunction_GET_SELF(cfunc), args, kws))if (call_trace(tstate->c_profilefunc, tstate->c_profileobj , tstate, tstate->frame, 0, cfunc)) result = __null; else { result = fn((((PyCFunctionObject *)cfunc) -> m_ml -> ml_flags & 0x0020 ? __null : ((PyCFunctionObject *)cfunc) -> m_self ), args, kws); if (tstate->c_profilefunc != __null) { if ( result == __null) { call_trace_protected(tstate->c_profilefunc , tstate->c_profileobj, tstate, tstate->frame, 3, cfunc ); } else { if (call_trace(tstate->c_profilefunc, tstate-> c_profileobj, tstate, tstate->frame, 3, cfunc)) { _Py_DECREF (((PyObject*)(result))); result = __null; } } } }; | |||
426 | /* write changes back to locals? */ | |||
427 | PyFrame_FastToLocals(frame); | |||
428 | tstate->frame = frame->f_back; | |||
429 | ||||
430 | error: | |||
431 | Py_XDECREF(frame)_Py_XDECREF(((PyObject*)(frame))); | |||
432 | Py_XDECREF(globals)_Py_XDECREF(((PyObject*)(globals))); | |||
433 | Py_XDECREF(code)_Py_XDECREF(((PyObject*)(code))); | |||
434 | return result; | |||
435 | } | |||
436 | else | |||
437 | return fn(PyCFunction_GET_SELF(cfunc)(((PyCFunctionObject *)cfunc) -> m_ml -> ml_flags & 0x0020 ? __null : ((PyCFunctionObject *)cfunc) -> m_self), args, kws); | |||
438 | } | |||
439 | ||||
440 | static | |||
441 | PyObject* | |||
442 | compile_and_invoke(Dispatcher *self, PyObject *args, PyObject *kws, PyObject *locals) | |||
443 | { | |||
444 | /* Compile a new one */ | |||
445 | PyObject *cfa, *cfunc, *retval; | |||
446 | cfa = PyObject_GetAttrString((PyObject*)self, "_compile_for_args"); | |||
447 | if (cfa == NULL__null) | |||
448 | return NULL__null; | |||
449 | ||||
450 | /* NOTE: we call the compiled function ourselves instead of | |||
451 | letting the Python derived class do it. This is for proper | |||
452 | behaviour of globals() in jitted functions (issue #476). */ | |||
453 | cfunc = PyObject_Call(cfa, args, kws); | |||
454 | Py_DECREF(cfa)_Py_DECREF(((PyObject*)(cfa))); | |||
455 | ||||
456 | if (cfunc == NULL__null) | |||
457 | return NULL__null; | |||
458 | ||||
459 | if (PyObject_TypeCheck(cfunc, &PyCFunction_Type)((((PyObject*)(cfunc))->ob_type) == (&PyCFunction_Type ) || PyType_IsSubtype((((PyObject*)(cfunc))->ob_type), (& PyCFunction_Type)))) { | |||
460 | retval = call_cfunc(self, cfunc, args, kws, locals); | |||
461 | } else { | |||
462 | /* Re-enter interpreter */ | |||
463 | retval = PyObject_Call(cfunc, args, kws); | |||
464 | } | |||
465 | Py_DECREF(cfunc)_Py_DECREF(((PyObject*)(cfunc))); | |||
466 | ||||
467 | return retval; | |||
468 | } | |||
469 | ||||
470 | /* A copy of compile_and_invoke, that only compiles. This is needed for CUDA | |||
471 | * kernels, because its overloads are Python instances of the _Kernel class, | |||
472 | * rather than compiled functions. Once CUDA overloads are compiled functions, | |||
473 | * cuda_compile_only can be removed. */ | |||
474 | static | |||
475 | PyObject* | |||
476 | cuda_compile_only(Dispatcher *self, PyObject *args, PyObject *kws, PyObject *locals) | |||
477 | { | |||
478 | /* Compile a new one */ | |||
479 | PyObject *cfa, *cfunc; | |||
480 | cfa = PyObject_GetAttrString((PyObject*)self, "_compile_for_args"); | |||
481 | if (cfa == NULL__null) | |||
482 | return NULL__null; | |||
483 | ||||
484 | cfunc = PyObject_Call(cfa, args, kws); | |||
485 | Py_DECREF(cfa)_Py_DECREF(((PyObject*)(cfa))); | |||
486 | ||||
487 | return cfunc; | |||
488 | } | |||
489 | ||||
490 | static int | |||
491 | find_named_args(Dispatcher *self, PyObject **pargs, PyObject **pkws) | |||
492 | { | |||
493 | PyObject *oldargs = *pargs, *newargs; | |||
494 | PyObject *kws = *pkws; | |||
495 | Py_ssize_t pos_args = PyTuple_GET_SIZE(oldargs)(((PyVarObject*)(((static_cast<void> (0)), (PyTupleObject *)(oldargs))))->ob_size); | |||
496 | Py_ssize_t named_args, total_args, i; | |||
497 | Py_ssize_t func_args = PyTuple_GET_SIZE(self->argnames)(((PyVarObject*)(((static_cast<void> (0)), (PyTupleObject *)(self->argnames))))->ob_size); | |||
498 | Py_ssize_t defaults = PyTuple_GET_SIZE(self->defargs)(((PyVarObject*)(((static_cast<void> (0)), (PyTupleObject *)(self->defargs))))->ob_size); | |||
499 | /* Last parameter with a default value */ | |||
500 | Py_ssize_t last_def = (self->has_stararg) | |||
501 | ? func_args - 2 | |||
502 | : func_args - 1; | |||
503 | /* First parameter with a default value */ | |||
504 | Py_ssize_t first_def = last_def - defaults + 1; | |||
505 | /* Minimum number of required arguments */ | |||
506 | Py_ssize_t minargs = first_def; | |||
507 | ||||
508 | if (kws != NULL__null) | |||
509 | named_args = PyDict_Size(kws); | |||
510 | else | |||
511 | named_args = 0; | |||
512 | total_args = pos_args + named_args; | |||
513 | if (!self->has_stararg && total_args > func_args) { | |||
514 | PyErr_Format(PyExc_TypeError, | |||
515 | "too many arguments: expected %d, got %d", | |||
516 | (int) func_args, (int) total_args); | |||
517 | return -1; | |||
518 | } | |||
519 | else if (total_args < minargs) { | |||
520 | if (minargs == func_args) | |||
521 | PyErr_Format(PyExc_TypeError, | |||
522 | "not enough arguments: expected %d, got %d", | |||
523 | (int) minargs, (int) total_args); | |||
524 | else | |||
525 | PyErr_Format(PyExc_TypeError, | |||
526 | "not enough arguments: expected at least %d, got %d", | |||
527 | (int) minargs, (int) total_args); | |||
528 | return -1; | |||
529 | } | |||
530 | newargs = PyTuple_New(func_args); | |||
531 | if (!newargs) | |||
532 | return -1; | |||
533 | /* First pack the stararg */ | |||
534 | if (self->has_stararg) { | |||
535 | Py_ssize_t stararg_size = Py_MAX(0, pos_args - func_args + 1)(((0) > (pos_args - func_args + 1)) ? (0) : (pos_args - func_args + 1)); | |||
536 | PyObject *stararg = PyTuple_New(stararg_size); | |||
537 | if (!stararg) { | |||
538 | Py_DECREF(newargs)_Py_DECREF(((PyObject*)(newargs))); | |||
539 | return -1; | |||
540 | } | |||
541 | for (i = 0; i < stararg_size; i++) { | |||
542 | PyObject *value = PyTuple_GET_ITEM(oldargs, func_args - 1 + i)(((static_cast<void> (0)), (PyTupleObject *)(oldargs))-> ob_item[func_args - 1 + i]); | |||
543 | Py_INCREF(value)_Py_INCREF(((PyObject*)(value))); | |||
544 | PyTuple_SET_ITEM(stararg, i, value)PyTuple_SetItem(stararg, i, value); | |||
545 | } | |||
546 | /* Put it in last position */ | |||
547 | PyTuple_SET_ITEM(newargs, func_args - 1, stararg)PyTuple_SetItem(newargs, func_args - 1, stararg); | |||
548 | ||||
549 | } | |||
550 | for (i = 0; i < pos_args; i++) { | |||
551 | PyObject *value = PyTuple_GET_ITEM(oldargs, i)(((static_cast<void> (0)), (PyTupleObject *)(oldargs))-> ob_item[i]); | |||
552 | if (self->has_stararg && i >= func_args - 1) { | |||
553 | /* Skip stararg */ | |||
554 | break; | |||
555 | } | |||
556 | Py_INCREF(value)_Py_INCREF(((PyObject*)(value))); | |||
557 | PyTuple_SET_ITEM(newargs, i, value)PyTuple_SetItem(newargs, i, value); | |||
558 | } | |||
559 | ||||
560 | /* Iterate over missing positional arguments, try to find them in | |||
561 | named arguments or default values. */ | |||
562 | for (i = pos_args; i < func_args; i++) { | |||
563 | PyObject *name = PyTuple_GET_ITEM(self->argnames, i)(((static_cast<void> (0)), (PyTupleObject *)(self->argnames ))->ob_item[i]); | |||
564 | if (self->has_stararg && i >= func_args - 1) { | |||
565 | /* Skip stararg */ | |||
566 | break; | |||
567 | } | |||
568 | if (kws != NULL__null) { | |||
569 | /* Named argument? */ | |||
570 | PyObject *value = PyDict_GetItem(kws, name); | |||
571 | if (value != NULL__null) { | |||
572 | Py_INCREF(value)_Py_INCREF(((PyObject*)(value))); | |||
573 | PyTuple_SET_ITEM(newargs, i, value)PyTuple_SetItem(newargs, i, value); | |||
574 | named_args--; | |||
575 | continue; | |||
576 | } | |||
577 | } | |||
578 | if (i >= first_def && i <= last_def) { | |||
579 | /* Argument has a default value? */ | |||
580 | PyObject *value = PyTuple_GET_ITEM(self->defargs, i - first_def)(((static_cast<void> (0)), (PyTupleObject *)(self->defargs ))->ob_item[i - first_def]); | |||
581 | Py_INCREF(value)_Py_INCREF(((PyObject*)(value))); | |||
582 | PyTuple_SET_ITEM(newargs, i, value)PyTuple_SetItem(newargs, i, value); | |||
583 | continue; | |||
584 | } | |||
585 | else if (i < func_args - 1 || !self->has_stararg) { | |||
586 | PyErr_Format(PyExc_TypeError, | |||
587 | "missing argument '%s'", | |||
588 | PyString_AsStringPyUnicode_AsUTF8(name)); | |||
589 | Py_DECREF(newargs)_Py_DECREF(((PyObject*)(newargs))); | |||
590 | return -1; | |||
591 | } | |||
592 | } | |||
593 | if (named_args) { | |||
594 | PyErr_Format(PyExc_TypeError, | |||
595 | "some keyword arguments unexpected"); | |||
596 | Py_DECREF(newargs)_Py_DECREF(((PyObject*)(newargs))); | |||
597 | return -1; | |||
598 | } | |||
599 | *pargs = newargs; | |||
600 | *pkws = NULL__null; | |||
601 | return 0; | |||
602 | } | |||
603 | ||||
604 | ||||
605 | /* | |||
606 | * Management of thread-local | |||
607 | */ | |||
608 | ||||
609 | #ifdef _MSC_VER | |||
610 | #define THREAD_LOCAL(ty)__thread ty __declspec(thread) ty | |||
611 | #else | |||
612 | /* Non-standard C99 extension that's understood by gcc and clang */ | |||
613 | #define THREAD_LOCAL(ty)__thread ty __thread ty | |||
614 | #endif | |||
615 | ||||
616 | static THREAD_LOCAL(bool)__thread bool use_tls_target_stack; | |||
617 | ||||
618 | ||||
619 | struct raii_use_tls_target_stack { | |||
620 | bool old_setting; | |||
621 | ||||
622 | raii_use_tls_target_stack(bool new_setting) | |||
623 | : old_setting(use_tls_target_stack) | |||
624 | { | |||
625 | use_tls_target_stack = new_setting; | |||
626 | } | |||
627 | ||||
628 | ~raii_use_tls_target_stack() { | |||
629 | use_tls_target_stack = old_setting; | |||
630 | } | |||
631 | }; | |||
632 | ||||
633 | static PyObject* | |||
634 | Dispatcher_call(Dispatcher *self, PyObject *args, PyObject *kws) | |||
635 | { | |||
636 | PyObject *tmptype, *retval = NULL__null; | |||
637 | int *tys = NULL__null; | |||
638 | int argct; | |||
639 | int i; | |||
640 | int prealloc[24]; | |||
641 | int matches; | |||
642 | PyObject *cfunc; | |||
643 | PyThreadState *ts = PyThreadState_Get(); | |||
644 | PyObject *locals = NULL__null; | |||
645 | ||||
646 | // Check TLS target stack | |||
647 | if (use_tls_target_stack) { | |||
648 | raii_use_tls_target_stack turn_off(false); | |||
649 | PyObject * meth_call_tls_target; | |||
650 | meth_call_tls_target = PyObject_GetAttrString((PyObject*)self, | |||
651 | "_call_tls_target"); | |||
652 | if (!meth_call_tls_target) return NULL__null; | |||
653 | // Transfer control to self._call_tls_target | |||
654 | retval = PyObject_Call(meth_call_tls_target, args, kws); | |||
655 | Py_DECREF(meth_call_tls_target)_Py_DECREF(((PyObject*)(meth_call_tls_target))); | |||
656 | return retval; | |||
657 | } | |||
658 | ||||
659 | /* If compilation is enabled, ensure that an exact match is found and if | |||
660 | * not compile one */ | |||
661 | int exact_match_required = self->can_compile ? 1 : self->exact_match_required; | |||
662 | ||||
663 | if (ts->use_tracing && ts->c_profilefunc) { | |||
664 | locals = PyEval_GetLocals(); | |||
665 | if (locals == NULL__null) { | |||
666 | goto CLEANUP; | |||
667 | } | |||
668 | } | |||
669 | if (self->fold_args) { | |||
670 | if (find_named_args(self, &args, &kws)) | |||
671 | return NULL__null; | |||
672 | } | |||
673 | else | |||
674 | Py_INCREF(args)_Py_INCREF(((PyObject*)(args))); | |||
675 | /* Now we own a reference to args */ | |||
676 | ||||
677 | argct = PySequence_Fast_GET_SIZE(args)(((((((PyObject*)(args))->ob_type))->tp_flags & ((1UL << 25))) != 0) ? ((static_cast<void> (0)), (((PyVarObject *)(args))->ob_size)) : (((PyVarObject*)(((static_cast<void > (0)), (PyTupleObject *)(args))))->ob_size)); | |||
678 | ||||
679 | if (argct < (Py_ssize_t) (sizeof(prealloc) / sizeof(int))) | |||
680 | tys = prealloc; | |||
681 | else | |||
682 | tys = new int[argct]; | |||
683 | ||||
684 | for (i = 0; i < argct; ++i) { | |||
685 | tmptype = PySequence_Fast_GET_ITEM(args, i)(((((((PyObject*)(args))->ob_type))->tp_flags & ((1UL << 25))) != 0) ? (((PyListObject *)(args))->ob_item [i]) : (((static_cast<void> (0)), (PyTupleObject *)(args ))->ob_item[i])); | |||
686 | tys[i] = typeof_typecode((PyObject *) self, tmptype); | |||
687 | if (tys[i] == -1) { | |||
688 | if (self->can_fallback){ | |||
689 | /* We will clear the exception if fallback is allowed. */ | |||
690 | PyErr_Clear(); | |||
691 | } else { | |||
692 | goto CLEANUP; | |||
693 | } | |||
694 | } | |||
695 | } | |||
696 | ||||
697 | /* We only allow unsafe conversions if compilation of new specializations | |||
698 | has been disabled. | |||
699 | ||||
700 | Note that the number of matches is returned in matches by resolve, which | |||
701 | accepts it as a reference. */ | |||
702 | cfunc = self->resolve(tys, matches, !self->can_compile, | |||
703 | exact_match_required); | |||
704 | ||||
705 | if (matches == 0 && !self->can_compile) { | |||
706 | /* | |||
707 | * If we can't compile a new specialization, look for | |||
708 | * matching signatures for which conversions haven't been | |||
709 | * registered on the C++ TypeManager. | |||
710 | */ | |||
711 | int res = search_new_conversions((PyObject *) self, args, kws); | |||
712 | if (res < 0) { | |||
713 | retval = NULL__null; | |||
714 | goto CLEANUP; | |||
715 | } | |||
716 | if (res > 0) { | |||
717 | /* Retry with the newly registered conversions */ | |||
718 | cfunc = self->resolve(tys, matches, !self->can_compile, | |||
719 | exact_match_required); | |||
720 | } | |||
721 | } | |||
722 | if (matches == 1) { | |||
723 | /* Definition is found */ | |||
724 | retval = call_cfunc(self, cfunc, args, kws, locals); | |||
725 | } else if (matches == 0) { | |||
726 | /* No matching definition */ | |||
727 | if (self->can_compile) { | |||
728 | retval = compile_and_invoke(self, args, kws, locals); | |||
729 | } else if (self->fallbackdef) { | |||
730 | /* Have object fallback */ | |||
731 | retval = call_cfunc(self, self->fallbackdef, args, kws, locals); | |||
732 | } else { | |||
733 | /* Raise TypeError */ | |||
734 | explain_matching_error((PyObject *) self, args, kws); | |||
735 | retval = NULL__null; | |||
736 | } | |||
737 | } else if (self->can_compile) { | |||
738 | /* Ambiguous, but are allowed to compile */ | |||
739 | retval = compile_and_invoke(self, args, kws, locals); | |||
740 | } else { | |||
741 | /* Ambiguous */ | |||
742 | explain_ambiguous((PyObject *) self, args, kws); | |||
743 | retval = NULL__null; | |||
744 | } | |||
745 | ||||
746 | CLEANUP: | |||
747 | if (tys != prealloc) | |||
748 | delete[] tys; | |||
749 | Py_DECREF(args)_Py_DECREF(((PyObject*)(args))); | |||
750 | ||||
751 | return retval; | |||
752 | } | |||
753 | ||||
754 | /* Based on Dispatcher_call above, with the following differences: | |||
755 | 1. It does not invoke the definition of the function. | |||
756 | 2. It returns the definition, instead of a value returned by the function. | |||
757 | ||||
758 | This is because CUDA functions are, at present, _Kernel objects rather than | |||
759 | compiled functions. */ | |||
760 | static PyObject* | |||
761 | Dispatcher_cuda_call(Dispatcher *self, PyObject *args, PyObject *kws) | |||
762 | { | |||
763 | PyObject *tmptype, *retval = NULL__null; | |||
764 | int *tys = NULL__null; | |||
765 | int argct; | |||
766 | int i; | |||
767 | int prealloc[24]; | |||
768 | int matches; | |||
769 | PyObject *cfunc; | |||
770 | PyThreadState *ts = PyThreadState_Get(); | |||
771 | PyObject *locals = NULL__null; | |||
772 | ||||
773 | /* If compilation is enabled, ensure that an exact match is found and if | |||
774 | * not compile one */ | |||
775 | int exact_match_required = self->can_compile ? 1 : self->exact_match_required; | |||
776 | ||||
777 | if (ts->use_tracing && ts->c_profilefunc) { | |||
778 | locals = PyEval_GetLocals(); | |||
779 | if (locals == NULL__null) { | |||
780 | goto CLEANUP; | |||
781 | } | |||
782 | } | |||
783 | if (self->fold_args) { | |||
784 | if (find_named_args(self, &args, &kws)) | |||
785 | return NULL__null; | |||
786 | } | |||
787 | else | |||
788 | Py_INCREF(args)_Py_INCREF(((PyObject*)(args))); | |||
789 | /* Now we own a reference to args */ | |||
790 | ||||
791 | argct = PySequence_Fast_GET_SIZE(args)(((((((PyObject*)(args))->ob_type))->tp_flags & ((1UL << 25))) != 0) ? ((static_cast<void> (0)), (((PyVarObject *)(args))->ob_size)) : (((PyVarObject*)(((static_cast<void > (0)), (PyTupleObject *)(args))))->ob_size)); | |||
792 | ||||
793 | if (argct < (Py_ssize_t) (sizeof(prealloc) / sizeof(int))) | |||
794 | tys = prealloc; | |||
795 | else | |||
796 | tys = new int[argct]; | |||
797 | ||||
798 | for (i = 0; i < argct; ++i) { | |||
799 | tmptype = PySequence_Fast_GET_ITEM(args, i)(((((((PyObject*)(args))->ob_type))->tp_flags & ((1UL << 25))) != 0) ? (((PyListObject *)(args))->ob_item [i]) : (((static_cast<void> (0)), (PyTupleObject *)(args ))->ob_item[i])); | |||
800 | tys[i] = typeof_typecode((PyObject *) self, tmptype); | |||
801 | if (tys[i] == -1) { | |||
802 | if (self->can_fallback){ | |||
803 | /* We will clear the exception if fallback is allowed. */ | |||
804 | PyErr_Clear(); | |||
805 | } else { | |||
806 | goto CLEANUP; | |||
807 | } | |||
808 | } | |||
809 | } | |||
810 | ||||
811 | /* We only allow unsafe conversions if compilation of new specializations | |||
812 | has been disabled. */ | |||
813 | cfunc = self->resolve(tys, matches, !self->can_compile, | |||
814 | exact_match_required); | |||
815 | ||||
816 | if (matches == 0 && !self->can_compile) { | |||
817 | /* | |||
818 | * If we can't compile a new specialization, look for | |||
819 | * matching signatures for which conversions haven't been | |||
820 | * registered on the C++ TypeManager. | |||
821 | */ | |||
822 | int res = search_new_conversions((PyObject *) self, args, kws); | |||
823 | if (res < 0) { | |||
824 | retval = NULL__null; | |||
825 | goto CLEANUP; | |||
826 | } | |||
827 | if (res > 0) { | |||
828 | /* Retry with the newly registered conversions */ | |||
829 | cfunc = self->resolve(tys, matches, !self->can_compile, | |||
830 | exact_match_required); | |||
831 | } | |||
832 | } | |||
833 | ||||
834 | if (matches == 1) { | |||
835 | /* Definition is found */ | |||
836 | retval = cfunc; | |||
837 | Py_INCREF(retval)_Py_INCREF(((PyObject*)(retval))); | |||
838 | } else if (matches == 0) { | |||
839 | /* No matching definition */ | |||
840 | if (self->can_compile) { | |||
841 | retval = cuda_compile_only(self, args, kws, locals); | |||
842 | } else if (self->fallbackdef) { | |||
843 | /* Have object fallback */ | |||
844 | retval = call_cfunc(self, self->fallbackdef, args, kws, locals); | |||
845 | } else { | |||
846 | /* Raise TypeError */ | |||
847 | explain_matching_error((PyObject *) self, args, kws); | |||
848 | retval = NULL__null; | |||
849 | } | |||
850 | } else if (self->can_compile) { | |||
851 | /* Ambiguous, but are allowed to compile */ | |||
852 | retval = cuda_compile_only(self, args, kws, locals); | |||
853 | } else { | |||
854 | /* Ambiguous */ | |||
855 | explain_ambiguous((PyObject *) self, args, kws); | |||
856 | retval = NULL__null; | |||
857 | } | |||
858 | ||||
859 | CLEANUP: | |||
860 | if (tys != prealloc) | |||
861 | delete[] tys; | |||
862 | Py_DECREF(args)_Py_DECREF(((PyObject*)(args))); | |||
863 | ||||
864 | return retval; | |||
865 | } | |||
866 | ||||
867 | static int | |||
868 | import_devicearray(void) | |||
869 | { | |||
870 | PyObject *devicearray = PyImport_ImportModule("numba._devicearray"); | |||
871 | if (devicearray == NULL__null) { | |||
872 | return -1; | |||
873 | } | |||
874 | Py_DECREF(devicearray)_Py_DECREF(((PyObject*)(devicearray))); | |||
875 | ||||
876 | DeviceArray_API = (void**)PyCapsule_Import("numba._devicearray._DEVICEARRAY_API", 0); | |||
877 | if (DeviceArray_API == NULL__null) { | |||
878 | return -1; | |||
879 | } | |||
880 | ||||
881 | return 0; | |||
882 | } | |||
883 | ||||
884 | static PyMethodDef Dispatcher_methods[] = { | |||
885 | { "_clear", (PyCFunction)Dispatcher_clear, METH_NOARGS0x0004, NULL__null }, | |||
886 | { "_insert", (PyCFunction)Dispatcher_Insert, METH_VARARGS0x0001 | METH_KEYWORDS0x0002, | |||
887 | "insert new definition"}, | |||
888 | { "_cuda_call", (PyCFunction)Dispatcher_cuda_call, | |||
889 | METH_VARARGS0x0001 | METH_KEYWORDS0x0002, "CUDA call resolution" }, | |||
890 | { NULL__null }, | |||
891 | }; | |||
892 | ||||
893 | static PyMemberDef Dispatcher_members[] = { | |||
894 | {(char*)"_can_compile", T_BOOL14, offsetof(Dispatcher, can_compile)__builtin_offsetof(Dispatcher, can_compile), 0, NULL__null }, | |||
895 | {NULL__null} /* Sentinel */ | |||
896 | }; | |||
897 | ||||
898 | ||||
899 | static PyTypeObject DispatcherType = { | |||
900 | PyVarObject_HEAD_INIT(NULL, 0){ { 1, __null }, 0 }, | |||
901 | "_dispatcher.Dispatcher", /* tp_name */ | |||
902 | sizeof(Dispatcher), /* tp_basicsize */ | |||
903 | 0, /* tp_itemsize */ | |||
904 | (destructor)Dispatcher_dealloc, /* tp_dealloc */ | |||
905 | 0, /* tp_print */ | |||
906 | 0, /* tp_getattr */ | |||
907 | 0, /* tp_setattr */ | |||
908 | 0, /* tp_compare */ | |||
909 | 0, /* tp_repr */ | |||
910 | 0, /* tp_as_number */ | |||
911 | 0, /* tp_as_sequence */ | |||
912 | 0, /* tp_as_mapping */ | |||
913 | 0, /* tp_hash */ | |||
914 | (PyCFunctionWithKeywords)Dispatcher_call, /* tp_call*/ | |||
915 | 0, /* tp_str*/ | |||
916 | 0, /* tp_getattro*/ | |||
917 | 0, /* tp_setattro*/ | |||
918 | 0, /* tp_as_buffer*/ | |||
919 | Py_TPFLAGS_DEFAULT( 0 | (1UL << 18) | 0) | Py_TPFLAGS_BASETYPE(1UL << 10) | Py_TPFLAGS_HAVE_GC(1UL << 14), /* tp_flags*/ | |||
920 | "Dispatcher object", /* tp_doc */ | |||
921 | (traverseproc) Dispatcher_traverse, /* tp_traverse */ | |||
922 | 0, /* tp_clear */ | |||
923 | 0, /* tp_richcompare */ | |||
924 | 0, /* tp_weaklistoffset */ | |||
925 | 0, /* tp_iter */ | |||
926 | 0, /* tp_iternext */ | |||
927 | Dispatcher_methods, /* tp_methods */ | |||
928 | Dispatcher_members, /* tp_members */ | |||
929 | 0, /* tp_getset */ | |||
930 | 0, /* tp_base */ | |||
931 | 0, /* tp_dict */ | |||
932 | 0, /* tp_descr_get */ | |||
933 | 0, /* tp_descr_set */ | |||
934 | 0, /* tp_dictoffset */ | |||
935 | (initproc)Dispatcher_init, /* tp_init */ | |||
936 | 0, /* tp_alloc */ | |||
937 | 0, /* tp_new */ | |||
938 | 0, /* tp_free */ | |||
939 | 0, /* tp_is_gc */ | |||
940 | 0, /* tp_bases */ | |||
941 | 0, /* tp_mro */ | |||
942 | 0, /* tp_cache */ | |||
943 | 0, /* tp_subclasses */ | |||
944 | 0, /* tp_weaklist */ | |||
945 | 0, /* tp_del */ | |||
946 | 0, /* tp_version_tag */ | |||
947 | 0, /* tp_finalize */ | |||
948 | #if PY_MAJOR_VERSION3 == 3 | |||
949 | /* Python 3.8 has two slots, 3.9 has one. */ | |||
950 | #if PY_MINOR_VERSION8 > 7 | |||
951 | 0, /* tp_vectorcall */ | |||
952 | #if PY_MINOR_VERSION8 == 8 | |||
953 | 0, /* tp_print */ | |||
954 | #endif | |||
955 | #endif | |||
956 | #endif | |||
957 | }; | |||
958 | ||||
959 | ||||
960 | static PyObject *compute_fingerprint(PyObject *self, PyObject *args) | |||
961 | { | |||
962 | PyObject *val; | |||
963 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "O:compute_fingerprint", &val)) | |||
964 | return NULL__null; | |||
965 | return typeof_compute_fingerprint(val); | |||
966 | } | |||
967 | ||||
968 | static PyObject *set_use_tls_target_stack(PyObject *self, PyObject *args) | |||
969 | { | |||
970 | int val; | |||
971 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "p", &val)) | |||
972 | return NULL__null; | |||
973 | bool old = use_tls_target_stack; | |||
974 | use_tls_target_stack = val; | |||
975 | // return the old value | |||
976 | if (old) { | |||
977 | Py_RETURN_TRUEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_TrueStruct )))), ((PyObject *) &_Py_TrueStruct); | |||
978 | } else { | |||
979 | Py_RETURN_FALSEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_FalseStruct )))), ((PyObject *) &_Py_FalseStruct); | |||
980 | } | |||
981 | } | |||
982 | ||||
983 | static PyMethodDef ext_methods[] = { | |||
984 | #define declmethod(func) { #func , ( PyCFunction )func , METH_VARARGS0x0001 , NULL__null } | |||
985 | declmethod(typeof_init), | |||
986 | declmethod(compute_fingerprint), | |||
987 | declmethod(set_use_tls_target_stack), | |||
988 | { NULL__null }, | |||
989 | #undef declmethod | |||
990 | }; | |||
991 | ||||
992 | ||||
993 | MOD_INIT(_dispatcher)extern "C" PyObject* PyInit__dispatcher(void) { | |||
994 | if (import_devicearray() < 0) { | |||
| ||||
995 | PyErr_Print(); | |||
996 | PyErr_SetString(PyExc_ImportError, "numba._devicearray failed to import"); | |||
997 | return MOD_ERROR_VAL__null; | |||
998 | } | |||
999 | ||||
1000 | PyObject *m; | |||
1001 | MOD_DEF(m, "_dispatcher", "No docs", ext_methods){ static struct PyModuleDef moduledef = { { { 1, __null }, __null , 0, __null, }, "_dispatcher", "No docs", -1, ext_methods, __null , __null, __null, __null }; m = PyModule_Create2(&moduledef , 1013); } | |||
| ||||
1002 | if (m == NULL__null) | |||
1003 | return MOD_ERROR_VAL__null; | |||
1004 | ||||
1005 | DispatcherType.tp_new = PyType_GenericNew; | |||
1006 | if (PyType_Ready(&DispatcherType) < 0) { | |||
1007 | return MOD_ERROR_VAL__null; | |||
1008 | } | |||
1009 | Py_INCREF(&DispatcherType)_Py_INCREF(((PyObject*)(&DispatcherType))); | |||
1010 | PyModule_AddObject(m, "Dispatcher", (PyObject*)(&DispatcherType)); | |||
1011 | ||||
1012 | return MOD_SUCCESS_VAL(m)m; | |||
1013 | } |
1 | #ifndef PyModule_Create2 |
2 | PyObject* clang_analyzer_PyObject_New_Reference(); |
3 | PyObject* PyModule_Create2(PyModuleDef *def, int module_api_version) { |
4 | return clang_analyzer_PyObject_New_Reference(); |
5 | } |
6 | #else |
7 | #warning "API PyModule_Create2 is defined as a macro." |
8 | #endif |