pythonsupport.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. // Collects code that was copied in from cpython, for a couple of different reasons:
  2. // * We wanted to modify it to produce a more efficient version for our uses
  3. // * We needed to call it and it was static :(
  4. // * We wanted to call it and needed to backport it
  5. #ifndef CPY_PYTHONSUPPORT_H
  6. #define CPY_PYTHONSUPPORT_H
  7. #include <stdbool.h>
  8. #include <Python.h>
  9. #include "pythoncapi_compat.h"
  10. #include <frameobject.h>
  11. #include <assert.h>
  12. #include "mypyc_util.h"
  13. #ifdef __cplusplus
  14. extern "C" {
  15. #endif
  16. #if 0
  17. } // why isn't emacs smart enough to not indent this
  18. #endif
  19. /////////////////////////////////////////
  20. // Adapted from bltinmodule.c in Python 3.7.0
  21. _Py_IDENTIFIER(__mro_entries__);
  22. static PyObject*
  23. update_bases(PyObject *bases)
  24. {
  25. Py_ssize_t i, j;
  26. PyObject *base, *meth, *new_base, *result, *new_bases = NULL;
  27. PyObject *stack[1] = {bases};
  28. assert(PyTuple_Check(bases));
  29. Py_ssize_t nargs = PyTuple_GET_SIZE(bases);
  30. for (i = 0; i < nargs; i++) {
  31. base = PyTuple_GET_ITEM(bases, i);
  32. if (PyType_Check(base)) {
  33. if (new_bases) {
  34. /* If we already have made a replacement, then we append every normal base,
  35. otherwise just skip it. */
  36. if (PyList_Append(new_bases, base) < 0) {
  37. goto error;
  38. }
  39. }
  40. continue;
  41. }
  42. if (_PyObject_LookupAttrId(base, &PyId___mro_entries__, &meth) < 0) {
  43. goto error;
  44. }
  45. if (!meth) {
  46. if (new_bases) {
  47. if (PyList_Append(new_bases, base) < 0) {
  48. goto error;
  49. }
  50. }
  51. continue;
  52. }
  53. new_base = _PyObject_FastCall(meth, stack, 1);
  54. Py_DECREF(meth);
  55. if (!new_base) {
  56. goto error;
  57. }
  58. if (!PyTuple_Check(new_base)) {
  59. PyErr_SetString(PyExc_TypeError,
  60. "__mro_entries__ must return a tuple");
  61. Py_DECREF(new_base);
  62. goto error;
  63. }
  64. if (!new_bases) {
  65. /* If this is a first successful replacement, create new_bases list and
  66. copy previously encountered bases. */
  67. if (!(new_bases = PyList_New(i))) {
  68. goto error;
  69. }
  70. for (j = 0; j < i; j++) {
  71. base = PyTuple_GET_ITEM(bases, j);
  72. PyList_SET_ITEM(new_bases, j, base);
  73. Py_INCREF(base);
  74. }
  75. }
  76. j = PyList_GET_SIZE(new_bases);
  77. if (PyList_SetSlice(new_bases, j, j, new_base) < 0) {
  78. goto error;
  79. }
  80. Py_DECREF(new_base);
  81. }
  82. if (!new_bases) {
  83. return bases;
  84. }
  85. result = PyList_AsTuple(new_bases);
  86. Py_DECREF(new_bases);
  87. return result;
  88. error:
  89. Py_XDECREF(new_bases);
  90. return NULL;
  91. }
  92. // From Python 3.7's typeobject.c
  93. _Py_IDENTIFIER(__init_subclass__);
  94. static int
  95. init_subclass(PyTypeObject *type, PyObject *kwds)
  96. {
  97. PyObject *super, *func, *result;
  98. PyObject *args[2] = {(PyObject *)type, (PyObject *)type};
  99. super = _PyObject_FastCall((PyObject *)&PySuper_Type, args, 2);
  100. if (super == NULL) {
  101. return -1;
  102. }
  103. func = _PyObject_GetAttrId(super, &PyId___init_subclass__);
  104. Py_DECREF(super);
  105. if (func == NULL) {
  106. return -1;
  107. }
  108. result = _PyObject_FastCallDict(func, NULL, 0, kwds);
  109. Py_DECREF(func);
  110. if (result == NULL) {
  111. return -1;
  112. }
  113. Py_DECREF(result);
  114. return 0;
  115. }
  116. // Adapted from longobject.c in Python 3.7.0
  117. /* This function adapted from PyLong_AsLongLongAndOverflow, but with
  118. * some safety checks removed and specialized to only work for objects
  119. * that are already longs.
  120. * About half of the win this provides, though, just comes from being
  121. * able to inline the function, which in addition to saving function call
  122. * overhead allows the out-parameter overflow flag to be collapsed into
  123. * control flow.
  124. * Additionally, we check against the possible range of CPyTagged, not of
  125. * Py_ssize_t. */
  126. static inline Py_ssize_t
  127. CPyLong_AsSsize_tAndOverflow(PyObject *vv, int *overflow)
  128. {
  129. /* This version by Tim Peters */
  130. PyLongObject *v = (PyLongObject *)vv;
  131. size_t x, prev;
  132. Py_ssize_t res;
  133. Py_ssize_t i;
  134. int sign;
  135. *overflow = 0;
  136. res = -1;
  137. i = Py_SIZE(v);
  138. if (likely(i == 1)) {
  139. res = v->ob_digit[0];
  140. } else if (likely(i == 0)) {
  141. res = 0;
  142. } else if (i == -1) {
  143. res = -(sdigit)v->ob_digit[0];
  144. } else {
  145. sign = 1;
  146. x = 0;
  147. if (i < 0) {
  148. sign = -1;
  149. i = -(i);
  150. }
  151. while (--i >= 0) {
  152. prev = x;
  153. x = (x << PyLong_SHIFT) + v->ob_digit[i];
  154. if ((x >> PyLong_SHIFT) != prev) {
  155. *overflow = sign;
  156. goto exit;
  157. }
  158. }
  159. /* Haven't lost any bits, but casting to long requires extra
  160. * care (see comment above).
  161. */
  162. if (x <= (size_t)CPY_TAGGED_MAX) {
  163. res = (Py_ssize_t)x * sign;
  164. }
  165. else if (sign < 0 && x == CPY_TAGGED_ABS_MIN) {
  166. res = CPY_TAGGED_MIN;
  167. }
  168. else {
  169. *overflow = sign;
  170. /* res is already set to -1 */
  171. }
  172. }
  173. exit:
  174. return res;
  175. }
  176. // Adapted from listobject.c in Python 3.7.0
  177. static int
  178. list_resize(PyListObject *self, Py_ssize_t newsize)
  179. {
  180. PyObject **items;
  181. size_t new_allocated, num_allocated_bytes;
  182. Py_ssize_t allocated = self->allocated;
  183. /* Bypass realloc() when a previous overallocation is large enough
  184. to accommodate the newsize. If the newsize falls lower than half
  185. the allocated size, then proceed with the realloc() to shrink the list.
  186. */
  187. if (allocated >= newsize && newsize >= (allocated >> 1)) {
  188. assert(self->ob_item != NULL || newsize == 0);
  189. Py_SET_SIZE(self, newsize);
  190. return 0;
  191. }
  192. /* This over-allocates proportional to the list size, making room
  193. * for additional growth. The over-allocation is mild, but is
  194. * enough to give linear-time amortized behavior over a long
  195. * sequence of appends() in the presence of a poorly-performing
  196. * system realloc().
  197. * The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
  198. * Note: new_allocated won't overflow because the largest possible value
  199. * is PY_SSIZE_T_MAX * (9 / 8) + 6 which always fits in a size_t.
  200. */
  201. new_allocated = (size_t)newsize + (newsize >> 3) + (newsize < 9 ? 3 : 6);
  202. if (new_allocated > (size_t)PY_SSIZE_T_MAX / sizeof(PyObject *)) {
  203. PyErr_NoMemory();
  204. return -1;
  205. }
  206. if (newsize == 0)
  207. new_allocated = 0;
  208. num_allocated_bytes = new_allocated * sizeof(PyObject *);
  209. items = (PyObject **)PyMem_Realloc(self->ob_item, num_allocated_bytes);
  210. if (items == NULL) {
  211. PyErr_NoMemory();
  212. return -1;
  213. }
  214. self->ob_item = items;
  215. Py_SET_SIZE(self, newsize);
  216. self->allocated = new_allocated;
  217. return 0;
  218. }
  219. // Changed to use PyList_SetSlice instead of the internal list_ass_slice
  220. static PyObject *
  221. list_pop_impl(PyListObject *self, Py_ssize_t index)
  222. {
  223. PyObject *v;
  224. int status;
  225. if (Py_SIZE(self) == 0) {
  226. /* Special-case most common failure cause */
  227. PyErr_SetString(PyExc_IndexError, "pop from empty list");
  228. return NULL;
  229. }
  230. if (index < 0)
  231. index += Py_SIZE(self);
  232. if (index < 0 || index >= Py_SIZE(self)) {
  233. PyErr_SetString(PyExc_IndexError, "pop index out of range");
  234. return NULL;
  235. }
  236. v = self->ob_item[index];
  237. if (index == Py_SIZE(self) - 1) {
  238. status = list_resize(self, Py_SIZE(self) - 1);
  239. if (status >= 0)
  240. return v; /* and v now owns the reference the list had */
  241. else
  242. return NULL;
  243. }
  244. Py_INCREF(v);
  245. status = PyList_SetSlice((PyObject *)self, index, index+1, (PyObject *)NULL);
  246. if (status < 0) {
  247. Py_DECREF(v);
  248. return NULL;
  249. }
  250. return v;
  251. }
  252. // Tweaked to directly use CPyTagged
  253. static CPyTagged
  254. list_count(PyListObject *self, PyObject *value)
  255. {
  256. Py_ssize_t count = 0;
  257. Py_ssize_t i;
  258. for (i = 0; i < Py_SIZE(self); i++) {
  259. int cmp = PyObject_RichCompareBool(self->ob_item[i], value, Py_EQ);
  260. if (cmp > 0)
  261. count++;
  262. else if (cmp < 0)
  263. return CPY_INT_TAG;
  264. }
  265. return CPyTagged_ShortFromSsize_t(count);
  266. }
  267. #if PY_VERSION_HEX < 0x03080000
  268. static PyObject *
  269. _PyDict_GetItemStringWithError(PyObject *v, const char *key)
  270. {
  271. PyObject *kv, *rv;
  272. kv = PyUnicode_FromString(key);
  273. if (kv == NULL) {
  274. return NULL;
  275. }
  276. rv = PyDict_GetItemWithError(v, kv);
  277. Py_DECREF(kv);
  278. return rv;
  279. }
  280. #endif
  281. #define CPyUnicode_EqualToASCIIString(x, y) _PyUnicode_EqualToASCIIString(x, y)
  282. // Adapted from genobject.c in Python 3.7.2
  283. // Copied because it wasn't in 3.5.2 and it is undocumented anyways.
  284. /*
  285. * Set StopIteration with specified value. Value can be arbitrary object
  286. * or NULL.
  287. *
  288. * Returns 0 if StopIteration is set and -1 if any other exception is set.
  289. */
  290. static int
  291. CPyGen_SetStopIterationValue(PyObject *value)
  292. {
  293. PyObject *e;
  294. if (value == NULL ||
  295. (!PyTuple_Check(value) && !PyExceptionInstance_Check(value)))
  296. {
  297. /* Delay exception instantiation if we can */
  298. PyErr_SetObject(PyExc_StopIteration, value);
  299. return 0;
  300. }
  301. /* Construct an exception instance manually with
  302. * PyObject_CallOneArg and pass it to PyErr_SetObject.
  303. *
  304. * We do this to handle a situation when "value" is a tuple, in which
  305. * case PyErr_SetObject would set the value of StopIteration to
  306. * the first element of the tuple.
  307. *
  308. * (See PyErr_SetObject/_PyErr_CreateException code for details.)
  309. */
  310. e = PyObject_CallOneArg(PyExc_StopIteration, value);
  311. if (e == NULL) {
  312. return -1;
  313. }
  314. PyErr_SetObject(PyExc_StopIteration, e);
  315. Py_DECREF(e);
  316. return 0;
  317. }
  318. // Copied from dictobject.c and dictobject.h, these are not Public before
  319. // Python 3.8. Also remove some error checks that we do in the callers.
  320. typedef struct {
  321. PyObject_HEAD
  322. PyDictObject *dv_dict;
  323. } _CPyDictViewObject;
  324. static PyObject *
  325. _CPyDictView_New(PyObject *dict, PyTypeObject *type)
  326. {
  327. _CPyDictViewObject *dv = PyObject_GC_New(_CPyDictViewObject, type);
  328. if (dv == NULL)
  329. return NULL;
  330. Py_INCREF(dict);
  331. dv->dv_dict = (PyDictObject *)dict;
  332. PyObject_GC_Track(dv);
  333. return (PyObject *)dv;
  334. }
  335. #ifdef __cplusplus
  336. }
  337. #endif
  338. #if PY_VERSION_HEX >= 0x030A0000 // 3.10
  339. static int
  340. _CPyObject_HasAttrId(PyObject *v, _Py_Identifier *name) {
  341. PyObject *tmp = NULL;
  342. int result = _PyObject_LookupAttrId(v, name, &tmp);
  343. if (tmp) {
  344. Py_DECREF(tmp);
  345. }
  346. return result;
  347. }
  348. #else
  349. #define _CPyObject_HasAttrId _PyObject_HasAttrId
  350. #endif
  351. #if PY_VERSION_HEX < 0x03090000
  352. // OneArgs and NoArgs functions got added in 3.9
  353. #define _PyObject_CallMethodIdNoArgs(self, name) \
  354. _PyObject_CallMethodIdObjArgs((self), (name), NULL)
  355. #define _PyObject_CallMethodIdOneArg(self, name, arg) \
  356. _PyObject_CallMethodIdObjArgs((self), (name), (arg), NULL)
  357. #endif
  358. // Copied from genobject.c in Python 3.10
  359. static int
  360. gen_is_coroutine(PyObject *o)
  361. {
  362. if (PyGen_CheckExact(o)) {
  363. PyCodeObject *code = (PyCodeObject *)((PyGenObject*)o)->gi_code;
  364. if (code->co_flags & CO_ITERABLE_COROUTINE) {
  365. return 1;
  366. }
  367. }
  368. return 0;
  369. }
  370. /*
  371. * This helper function returns an awaitable for `o`:
  372. * - `o` if `o` is a coroutine-object;
  373. * - `type(o)->tp_as_async->am_await(o)`
  374. *
  375. * Raises a TypeError if it's not possible to return
  376. * an awaitable and returns NULL.
  377. */
  378. static PyObject *
  379. CPyCoro_GetAwaitableIter(PyObject *o)
  380. {
  381. unaryfunc getter = NULL;
  382. PyTypeObject *ot;
  383. if (PyCoro_CheckExact(o) || gen_is_coroutine(o)) {
  384. /* 'o' is a coroutine. */
  385. Py_INCREF(o);
  386. return o;
  387. }
  388. ot = Py_TYPE(o);
  389. if (ot->tp_as_async != NULL) {
  390. getter = ot->tp_as_async->am_await;
  391. }
  392. if (getter != NULL) {
  393. PyObject *res = (*getter)(o);
  394. if (res != NULL) {
  395. if (PyCoro_CheckExact(res) || gen_is_coroutine(res)) {
  396. /* __await__ must return an *iterator*, not
  397. a coroutine or another awaitable (see PEP 492) */
  398. PyErr_SetString(PyExc_TypeError,
  399. "__await__() returned a coroutine");
  400. Py_CLEAR(res);
  401. } else if (!PyIter_Check(res)) {
  402. PyErr_Format(PyExc_TypeError,
  403. "__await__() returned non-iterator "
  404. "of type '%.100s'",
  405. Py_TYPE(res)->tp_name);
  406. Py_CLEAR(res);
  407. }
  408. }
  409. return res;
  410. }
  411. PyErr_Format(PyExc_TypeError,
  412. "object %.100s can't be used in 'await' expression",
  413. ot->tp_name);
  414. return NULL;
  415. }
  416. #endif