|
12 | 12 | #include "numpy/arrayobject.h"
|
13 | 13 | #include "npy_import.h"
|
14 | 14 | #include "npy_static_data.h"
|
| 15 | +#include "extobj.h" |
15 | 16 |
|
16 | 17 | // static variables are zero-filled by default, no need to explicitly do so
|
17 | 18 | NPY_VISIBILITY_HIDDEN npy_interned_str_struct npy_interned_str;
|
18 | 19 | NPY_VISIBILITY_HIDDEN npy_static_pydata_struct npy_static_pydata;
|
19 | 20 | NPY_VISIBILITY_HIDDEN npy_static_cdata_struct npy_static_cdata;
|
20 | 21 |
|
| 22 | +#define INTERN_STRING(struct_member, string) \ |
| 23 | + assert(npy_interned_str.struct_member == NULL); \ |
| 24 | + npy_interned_str.struct_member = PyUnicode_InternFromString(string); \ |
| 25 | + if (npy_interned_str.struct_member == NULL) { \ |
| 26 | + return -1; \ |
| 27 | + } \ |
| 28 | + |
21 | 29 | NPY_NO_EXPORT int
|
22 | 30 | intern_strings(void)
|
23 | 31 | {
|
24 |
| - npy_interned_str.current_allocator = PyUnicode_InternFromString("current_allocator"); |
25 |
| - if (npy_interned_str.current_allocator == NULL) { |
26 |
| - return -1; |
27 |
| - } |
28 |
| - npy_interned_str.array = PyUnicode_InternFromString("__array__"); |
29 |
| - if (npy_interned_str.array == NULL) { |
30 |
| - return -1; |
31 |
| - } |
32 |
| - npy_interned_str.array_function = PyUnicode_InternFromString("__array_function__"); |
33 |
| - if (npy_interned_str.array_function == NULL) { |
34 |
| - return -1; |
35 |
| - } |
36 |
| - npy_interned_str.array_struct = PyUnicode_InternFromString("__array_struct__"); |
37 |
| - if (npy_interned_str.array_struct == NULL) { |
38 |
| - return -1; |
39 |
| - } |
40 |
| - npy_interned_str.array_priority = PyUnicode_InternFromString("__array_priority__"); |
41 |
| - if (npy_interned_str.array_priority == NULL) { |
42 |
| - return -1; |
43 |
| - } |
44 |
| - npy_interned_str.array_interface = PyUnicode_InternFromString("__array_interface__"); |
45 |
| - if (npy_interned_str.array_interface == NULL) { |
46 |
| - return -1; |
47 |
| - } |
48 |
| - npy_interned_str.array_ufunc = PyUnicode_InternFromString("__array_ufunc__"); |
49 |
| - if (npy_interned_str.array_ufunc == NULL) { |
50 |
| - return -1; |
51 |
| - } |
52 |
| - npy_interned_str.array_wrap = PyUnicode_InternFromString("__array_wrap__"); |
53 |
| - if (npy_interned_str.array_wrap == NULL) { |
54 |
| - return -1; |
55 |
| - } |
56 |
| - npy_interned_str.array_finalize = PyUnicode_InternFromString("__array_finalize__"); |
57 |
| - if (npy_interned_str.array_finalize == NULL) { |
58 |
| - return -1; |
59 |
| - } |
60 |
| - npy_interned_str.implementation = PyUnicode_InternFromString("_implementation"); |
61 |
| - if (npy_interned_str.implementation == NULL) { |
62 |
| - return -1; |
63 |
| - } |
64 |
| - npy_interned_str.axis1 = PyUnicode_InternFromString("axis1"); |
65 |
| - if (npy_interned_str.axis1 == NULL) { |
66 |
| - return -1; |
67 |
| - } |
68 |
| - npy_interned_str.axis2 = PyUnicode_InternFromString("axis2"); |
69 |
| - if (npy_interned_str.axis2 == NULL) { |
70 |
| - return -1; |
71 |
| - } |
72 |
| - npy_interned_str.like = PyUnicode_InternFromString("like"); |
73 |
| - if (npy_interned_str.like == NULL) { |
74 |
| - return -1; |
75 |
| - } |
76 |
| - npy_interned_str.numpy = PyUnicode_InternFromString("numpy"); |
77 |
| - if (npy_interned_str.numpy == NULL) { |
78 |
| - return -1; |
79 |
| - } |
80 |
| - npy_interned_str.where = PyUnicode_InternFromString("where"); |
81 |
| - if (npy_interned_str.where == NULL) { |
82 |
| - return -1; |
83 |
| - } |
84 |
| - npy_interned_str.convert = PyUnicode_InternFromString("convert"); |
85 |
| - if (npy_interned_str.convert == NULL) { |
86 |
| - return -1; |
87 |
| - } |
88 |
| - npy_interned_str.preserve = PyUnicode_InternFromString("preserve"); |
89 |
| - if (npy_interned_str.preserve == NULL) { |
90 |
| - return -1; |
91 |
| - } |
92 |
| - npy_interned_str.convert_if_no_array = PyU
F438
nicode_InternFromString("convert_if_no_array"); |
93 |
| - if (npy_interned_str.convert_if_no_array == NULL) { |
94 |
| - return -1; |
95 |
| - } |
96 |
| - npy_interned_str.cpu = PyUnicode_InternFromString("cpu"); |
97 |
| - if (npy_interned_str.cpu == NULL) { |
98 |
| - return -1; |
99 |
| - } |
100 |
| - npy_interned_str.dtype = PyUnicode_InternFromString("dtype"); |
101 |
| - if (npy_interned_str.dtype == NULL) { |
102 |
| - return -1; |
103 |
| - } |
104 |
| - npy_interned_str.array_err_msg_substr = PyUnicode_InternFromString( |
| 32 | + INTERN_STRING(current_allocator, "current_allocator"); |
| 33 | + INTERN_STRING(array, "__array__"); |
| 34 | + INTERN_STRING(array_function, "__array_function__"); |
| 35 | + INTERN_STRING(array_struct, "__array_struct__"); |
| 36 | + INTERN_STRING(array_priority, "__array_priority__"); |
| 37 | + INTERN_STRING(array_interface, "__array_interface__"); |
| 38 | + INTERN_STRING(array_ufunc, "__array_ufunc__"); |
| 39 | + INTERN_STRING(array_wrap, "__array_wrap__"); |
| 40 | + INTERN_STRING(array_finalize, "__array_finalize__"); |
| 41 | + INTERN_STRING(implementation, "_implementation"); |
| 42 | + INTERN_STRING(axis1, "axis1"); |
| 43 | + INTERN_STRING(axis2, "axis2"); |
| 44 | + INTERN_STRING(like, "like"); |
| 45 | + INTERN_STRING(numpy, "numpy"); |
| 46 | + INTERN_STRING(where, "where"); |
| 47 | + INTERN_STRING(convert, "convert"); |
| 48 | + INTERN_STRING(preserve, "preserve"); |
| 49 | + INTERN_STRING(convert_if_no_array, "convert_if_no_array"); |
| 50 | + INTERN_STRING(cpu, "cpu"); |
| 51 | + INTERN_STRING(dtype, "dtype"); |
| 52 | + INTERN_STRING( |
| 53 | + array_err_msg_substr, |
105 | 54 | "__array__() got an unexpected keyword argument 'copy'");
|
106 |
| - if (npy_interned_str.array_err_msg_substr == NULL) { |
107 |
| - return -1; |
108 |
| - } |
109 |
| - npy_interned_str.out = PyUnicode_InternFromString("out"); |
110 |
| - if (npy_interned_str.out == NULL) { |
111 |
| - return -1; |
112 |
| - } |
113 |
| - npy_interned_str.__dlpack__ = PyUnicode_InternFromString("__dlpack__"); |
114 |
| - if (npy_interned_str.__dlpack__ == NULL) { |
115 |
| - return -1; |
116 |
| - } |
117 |
| - npy_interned_str.pyvals_name = PyUnicode_InternFromString("UFUNC_PYVALS_NAME"); |
118 |
| - if (npy_interned_str.pyvals_name == NULL) { |
119 |
| - return -1; |
120 |
| - } |
| 55 | + INTERN_STRING(out, "out"); |
| 56 | + INTERN_STRING(errmode_strings[0], "ignore"); |
| 57 | + INTERN_STRING(errmode_strings[1], "warn"); |
| 58 | + INTERN_STRING(errmode_strings[2], "raise"); |
| 59 | + INTERN_STRING(errmode_strings[3], "call"); |
| 60 | + INTERN_STRING(errmode_strings[4], "print"); |
| 61 | + INTERN_STRING(errmode_strings[5], "log"); |
| 62 | + INTERN_STRING(__dlpack__, "__dlpack__"); |
| 63 | + INTERN_STRING(pyvals_name, "UFUNC_PYVALS_NAME"); |
121 | 64 | return 0;
|
122 | 65 | }
|
123 | 66 |
|
@@ -149,7 +92,13 @@ intern_strings(void)
|
149 | 92 | NPY_NO_EXPORT int
|
150 | 93 | initialize_static_globals(void)
|
151 | 94 | {
|
152 |
| - // cached reference to objects defined in python |
| 95 | + /* |
| 96 | + * Initialize contents of npy_static_pydata struct |
| 97 | + * |
| 98 | + * This struct holds cached references to python objects |
| 99 | + * that we want to keep alive for the lifetime of the |
| 100 | + * module for performance reasons |
| 101 | + */ |
153 | 102 |
|
154 | 103 | IMPORT_GLOBAL("math", "floor",
|
155 | 104 | npy_static_pydata.math_floor_func);
|
@@ -219,6 +168,32 @@ initialize_static_globals(void)
|
219 | 168 | }
|
220 | 169 | Py_DECREF(tmp);
|
221 | 170 |
|
| 171 | + npy_static_pydata.kwnames_is_copy = Py_BuildValue("(s)", "copy"); |
| 172 | + if (npy_static_pydata.kwnames_is_copy == NULL) { |
| 173 | + return -1; |
| 174 | + } |
| 175 | + |
| 176 | + npy_static_pydata.one_obj = PyLong_FromLong((long) 1); |
| 177 | + if (npy_static_pydata.one_obj == NULL) { |
| 178 | + return -1; |
| 179 | + } |
| 180 | + |
| 181 | + npy_static_pydata.zero_obj = PyLong_FromLong((long) 0); |
| 182 | + if (npy_static_pydata.zero_obj == NULL) { |
| 183 | + return -1; |
| 184 | + } |
| 185 | + |
| 186 | + /* |
| 187 | + * Initialize contents of npy_static_cdata struct |
| 188 | + * |
| 189 | + * Note that some entries are initialized elsewhere. Care |
| 190 | + * must be taken to ensure all entries are initialized during |
| 191 | + * module initialization and immutable thereafter. |
| 192 | + * |
| 193 | + * This struct holds global static caches. These are set |
| 194 | + * up this way for performance reasons. |
| 195 | + */ |
| 196 | + |
222 | 197 | PyObject *flags = PySys_GetObject("flags"); /* borrowed object */
|
223 | 198 | if (flags == NULL) {
|
224 | 199 | PyErr_SetString(PyExc_AttributeError, "cannot get sys.flags");
|
@@ -248,22 +223,40 @@ initialize_static_globals(void)
|
248 | 223 | }
|
249 | 224 | }
|
250 | 225 |
|
251 |
| - npy_static_pydata.kwnames_is_copy = Py_BuildValue("(s)", "copy"); |
252 |
| - if (npy_static_pydata.kwnames_is_copy == NULL) { |
253 |
| - return -1; |
254 |
| - } |
| 226 | + return 0; |
| 227 | +} |
| 228 | +/* |
| 229 | + * Verifies all entries in npy_interned_str and npy_static_pydata are |
| 230 | + * non-NULL. |
| 231 | + * |
| 232 | + * Called at the end of initialization for _multiarray_umath. Some |
| 233 | + * entries are initialized outside of this file because they depend on |
| 234 | + * items that are initialized late in module initialization but they |
| 235 | + * should all be initialized by the time this function is called. |
| 236 | + */ |
255 | 237 |
|
256 |
| - npy_static_pydata.one_obj = PyLong_FromLong((long) 1); |
257 |
| - if (npy_static_pydata.one_obj == NULL) { |
258 |
| - return -1; |
| 238 | +NPY_NO_EXPORT int |
| 239 | +verify_static_structs_initialized(void) { |
| 240 | + // verify all entries in npy_interned_str are filled in |
| 241 | + for (int i=0; i < (sizeof(npy_interned_str_struct)/sizeof(PyObject *)); i++) { |
| 242 | + if (*(((PyObject **)&npy_interned_str) + i) == NULL) { |
| 243 | + PyErr_Format( |
| 244 | + PyExc_SystemError, |
| 245 | + "NumPy internal error: NULL entry detected in " |
| 246 | + "npy_interned_str at index %d", i); |
| 247 | + return -1; |
| 248 | + } |
259 | 249 | }
|
260 | 250 |
|
261 |
| - npy_static_pydata.zero_obj = PyLong_FromLong((long) 0); |
262 |
| - if (npy_static_pydata.zero_obj == NULL) { |
263 |
| - return -1; |
| 251 | + // verify all entries in npy_static_pydata are filled in |
| 252 | + for (int i=0; i < (sizeof(npy_static_pydata_struct)/sizeof(PyObject *)); i++) { |
| 253 | + if (*(((PyObject **)&npy_static_pydata) + i) == NULL) { |
| 254 | + PyErr_Format( |
| 255 | + PyExc_SystemError, |
| 256 | + "NumPy internal error: NULL entry detected in " |
| 257 | + "npy_static_pydata at index %d", i); |
| 258 | + return -1; |
| 259 | + } |
264 | 260 | }
|
265 |
| - |
266 | 261 | return 0;
|
267 | 262 | }
|
268 |
| - |
269 |
| - |
0 commit comments