1 #ifndef MYPYC_UTIL_H
2 #define MYPYC_UTIL_H
3 
4 #include <Python.h>
5 #include <frameobject.h>
6 #include <assert.h>
7 
8 #if defined(__clang__) || defined(__GNUC__)
9 #define likely(x)       __builtin_expect((x),1)
10 #define unlikely(x)     __builtin_expect((x),0)
11 #define CPy_Unreachable() __builtin_unreachable()
12 #else
13 #define likely(x)       (x)
14 #define unlikely(x)     (x)
15 #define CPy_Unreachable() abort()
16 #endif
17 
18 #if defined(__clang__) || defined(__GNUC__)
19 #define CPy_NOINLINE __attribute__((noinline))
20 #elif defined(_MSC_VER)
21 #define CPy_NOINLINE __declspec(noinline)
22 #else
23 #define CPy_NOINLINE
24 #endif
25 
26 // INCREF and DECREF that assert the pointer is not NULL.
27 // asserts are disabled in release builds so there shouldn't be a perf hit.
28 // I'm honestly kind of surprised that this isn't done by default.
29 #define CPy_INCREF(p) do { assert(p); Py_INCREF(p); } while (0)
30 #define CPy_DECREF(p) do { assert(p); Py_DECREF(p); } while (0)
31 // Here just for consistency
32 #define CPy_XDECREF(p) Py_XDECREF(p)
33 
34 // Tagged integer -- our representation of Python 'int' objects.
35 // Small enough integers are represented as unboxed integers (shifted
36 // left by 1); larger integers (larger than 63 bits on a 64-bit
37 // platform) are stored as a tagged pointer (PyObject *)
38 // representing a Python int object, with the lowest bit set.
39 // Tagged integers are always normalized. A small integer *must not*
40 // have the tag bit set.
41 typedef size_t CPyTagged;
42 
43 typedef size_t CPyPtr;
44 
45 #define CPY_INT_BITS (CHAR_BIT * sizeof(CPyTagged))
46 
47 #define CPY_TAGGED_MAX (((Py_ssize_t)1 << (CPY_INT_BITS - 2)) - 1)
48 #define CPY_TAGGED_MIN (-((Py_ssize_t)1 << (CPY_INT_BITS - 2)))
49 #define CPY_TAGGED_ABS_MIN (0-(size_t)CPY_TAGGED_MIN)
50 
51 typedef PyObject CPyModule;
52 
53 // Tag bit used for long integers
54 #define CPY_INT_TAG 1
55 
56 typedef void (*CPyVTableItem)(void);
57 
CPyTagged_ShortFromInt(int x)58 static inline CPyTagged CPyTagged_ShortFromInt(int x) {
59     return x << 1;
60 }
61 
CPyTagged_ShortFromSsize_t(Py_ssize_t x)62 static inline CPyTagged CPyTagged_ShortFromSsize_t(Py_ssize_t x) {
63     return x << 1;
64 }
65 
66 #endif
67