From 4f2d3de9229a9c7d2ae6a978cda04ab2262209a8 Mon Sep 17 00:00:00 2001 From: Florian Angerer Date: Tue, 22 Mar 2022 16:43:56 +0100 Subject: [PATCH] Use HPyGlobal for global type vars --- numpy/core/include/numpy/ndarrayobject.h | 31 ++++++++++++++-- numpy/core/include/numpy/ndarraytypes.h | 1 - numpy/core/src/multiarray/arrayobject.h | 3 +- numpy/core/src/multiarray/ctors.c | 26 +++++++------- numpy/core/src/multiarray/descriptor.h | 3 +- numpy/core/src/multiarray/multiarraymodule.c | 38 +++++++++++++------- 6 files changed, 71 insertions(+), 31 deletions(-) diff --git a/numpy/core/include/numpy/ndarrayobject.h b/numpy/core/include/numpy/ndarrayobject.h index 78149a5ab77c..90898f30d779 100644 --- a/numpy/core/include/numpy/ndarrayobject.h +++ b/numpy/core/include/numpy/ndarrayobject.h @@ -24,13 +24,38 @@ extern "C" { /* C-API that requires previous API to be defined */ #define PyArray_DescrCheck(op) PyObject_TypeCheck(op, &PyArrayDescr_Type) -#define HPyArray_DescrCheck(ctx, op) HPy_TypeCheck(ctx, op, HPyArrayDescr_Type) +extern NPY_NO_EXPORT HPyGlobal HPyArrayDescr_Type; +static NPY_INLINE int +HPyArray_DescrCheck(HPyContext *ctx, HPy op) +{ + HPy array_descr_type = HPyGlobal_Load(ctx, HPyArrayDescr_Type); + int res = HPy_TypeCheck(ctx, op, array_descr_type); + HPy_Close(ctx, array_descr_type); + return res; +} #define PyArray_Check(op) PyObject_TypeCheck(op, &PyArray_Type) #define PyArray_CheckExact(op) (((PyObject*)(op))->ob_type == &PyArray_Type) -#define HPyArray_Check(ctx, op) HPy_TypeCheck(ctx, op, HPyArray_Type) -#define HPyArray_CheckExact(ctx, op) HPy_Is(ctx, op, HPyArray_Type) + +extern NPY_NO_EXPORT HPyGlobal HPyArray_Type; +static NPY_INLINE int +HPyArray_Check(HPyContext *ctx, HPy op) +{ + HPy array_type = HPyGlobal_Load(ctx, HPyArray_Type); + int res = HPy_TypeCheck(ctx, op, array_type); + HPy_Close(ctx, array_type); + return res; +} + +static NPY_INLINE int +HPyArray_CheckExact(HPyContext *ctx, HPy op) +{ + HPy array_type = HPyGlobal_Load(ctx, HPyArray_Type); + int res = HPy_Is(ctx, HPy_Type(ctx, op), array_type); + HPy_Close(ctx, array_type); + return res; +} #define PyArray_HasArrayInterfaceType(op, type, context, out) \ ((((out)=PyArray_FromStructInterface(op)) != Py_NotImplemented) || \ diff --git a/numpy/core/include/numpy/ndarraytypes.h b/numpy/core/include/numpy/ndarraytypes.h index 758913fa01ba..3b88d93b1750 100644 --- a/numpy/core/include/numpy/ndarraytypes.h +++ b/numpy/core/include/numpy/ndarraytypes.h @@ -2086,7 +2086,6 @@ typedef void (PyDataMem_EventHookFunc)(void *inp, void *outp, size_t size, #endif /* NPY_INTERNAL_BUILD */ - /* * Use the keyword NPY_DEPRECATED_INCLUDES to ensure that the header files * npy_*_*_deprecated_api.h are only included from here and nowhere else. diff --git a/numpy/core/src/multiarray/arrayobject.h b/numpy/core/src/multiarray/arrayobject.h index e8328ba3b50a..5f985b1f7c43 100644 --- a/numpy/core/src/multiarray/arrayobject.h +++ b/numpy/core/src/multiarray/arrayobject.h @@ -28,8 +28,9 @@ array_might_be_written(PyArrayObject *obj); static const int NPY_ARRAY_WARN_ON_WRITE = (1 << 31); extern NPY_NO_EXPORT HPyType_Spec PyArray_Type_spec; -extern NPY_NO_EXPORT HPy HPyArray_Type; +extern NPY_NO_EXPORT HPyGlobal HPyArray_Type; extern NPY_NO_EXPORT HPyType_Spec PyArrayFlags_Type_Spec; +extern NPY_NO_EXPORT HPyGlobal HPyArrayDescr_Type; NPY_NO_EXPORT int HPyArray_ElementStrides(HPyContext *ctx, HPy obj); diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c index b7ebd0f5b39b..a3a85574105f 100644 --- a/numpy/core/src/multiarray/ctors.c +++ b/numpy/core/src/multiarray/ctors.c @@ -912,8 +912,11 @@ HPyArray_NewFromDescr_int( * (since that function does nothing), or, for backward compatibility, * if it is None. */ - if (!HPy_Is(ctx, h_subtype, HPyArray_Type)) { - HPy ndarray_array_finalize = HPy_GetAttr_s(ctx, HPyArray_Type, "__array_finalize__"); + HPy array_type = HPyGlobal_Load(ctx, HPyArray_Type); + if (!HPy_Is(ctx, h_subtype, array_type)) { + HPy ndarray_array_finalize = HPy_GetAttr_s(ctx, array_type, "__array_finalize__"); + HPy_Close(ctx, array_type); + HPy func = HPy_GetAttr_s(ctx, h_subtype, "__array_finalize__"); if (HPy_IsNull(func)) { HPy_Close(ctx, ndarray_array_finalize); @@ -977,6 +980,8 @@ HPyArray_NewFromDescr_int( } } } + } else { + HPy_Close(ctx, array_type); } return result; @@ -1223,15 +1228,10 @@ HPyArray_NewLikeArrayWithShape(HPyContext *ctx, HPy prototype, NPY_ORDER order, /* If it's not KEEPORDER, this is simple */ if (order != NPY_KEEPORDER) { - ret = HPyArray_NewFromDescr(ctx, - subok ? HPy_Type(ctx, prototype) : HPyArray_Type, - dtype, - ndim, - dims, - NULL, - NULL, - order, - subok ? prototype : HPy_NULL); + HPy type = subok ? HPy_Type(ctx, prototype) : HPyGlobal_Load(ctx, HPyArray_Type); + ret = HPyArray_NewFromDescr(ctx, type, dtype, ndim, dims, NULL, NULL, + order, subok ? prototype : HPy_NULL); + HPy_Close(ctx, type); } /* KEEPORDER needs some analysis of the strides */ else { @@ -3213,11 +3213,13 @@ HPyArray_Zeros(HPyContext *ctx, int nd, npy_intp const *dims, HPy type, int is_f type = HPyArray_DescrFromType(ctx, NPY_DEFAULT_TYPE); } + HPy array_type = HPyGlobal_Load(ctx, HPyArray_Type); ret = HPyArray_NewFromDescr_int( - ctx, HPyArray_Type, type, + ctx, array_type, type, nd, dims, NULL, NULL, is_f_order, HPy_NULL, HPy_NULL, 1, 0); + HPy_Close(ctx, array_type); if (HPy_IsNull(ret)) { // HPY TODO: note that HPyArray_NewFromDescr_int still steals 'type_descr' on error diff --git a/numpy/core/src/multiarray/descriptor.h b/numpy/core/src/multiarray/descriptor.h index 6a9f90b3bcbd..aa7b559272b3 100644 --- a/numpy/core/src/multiarray/descriptor.h +++ b/numpy/core/src/multiarray/descriptor.h @@ -43,9 +43,8 @@ HPyArray_DescrNew(HPyContext *ctx, HPy h_base); NPY_NO_EXPORT PyArray_DTypeMeta PyArrayDescr_TypeFull; NPY_NO_EXPORT PyTypeObject *_PyArrayDescr_Type_p; -// HPY TODO: HACK storing handle in a global variable... // the variable is defined in multiarraymodule.c for now, // should be in/accesible via HPY API eventually -NPY_NO_EXPORT HPy HPyArrayDescr_Type; +NPY_NO_EXPORT extern HPyGlobal HPyArrayDescr_Type; #endif /* NUMPY_CORE_SRC_MULTIARRAY_DESCRIPTOR_H_ */ diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c index fdb962b4eae5..7c088721c11f 100644 --- a/numpy/core/src/multiarray/multiarraymodule.c +++ b/numpy/core/src/multiarray/multiarraymodule.c @@ -111,8 +111,8 @@ set_legacy_print_mode(PyObject *NPY_UNUSED(self), PyObject *args) NPY_NO_EXPORT PyTypeObject* _PyArray_Type_p = NULL; NPY_NO_EXPORT HPyContext *numpy_global_ctx = NULL; -NPY_NO_EXPORT HPy HPyArray_Type; -NPY_NO_EXPORT HPy HPyArrayDescr_Type; +NPY_NO_EXPORT HPyGlobal HPyArray_Type; +NPY_NO_EXPORT HPyGlobal HPyArrayDescr_Type; /* Only here for API compatibility */ NPY_NO_EXPORT PyTypeObject PyBigArray_Type; @@ -1693,6 +1693,7 @@ _hpy_array_fromobject_generic( HPyContext *ctx, HPy op, HPy type, _PyArray_CopyMode copy, NPY_ORDER order, npy_bool subok, int ndmin) { + HPy array_type = HPy_NULL; HPy ret = HPy_NULL; PyArrayObject *oparr; HPy oldtype = HPy_NULL; @@ -1704,14 +1705,15 @@ _hpy_array_fromobject_generic( HPyErr_SetString(ctx, ctx->h_ValueError, "ndmin bigger than allowable number of dimensions " "NPY_MAXDIMS (=%d)"/*, HPY TODO: NPY_MAXDIMS*/); - return HPy_NULL; + goto fail; } /* fast exit if simple call */ // HPY TODO (API): original code uses "check exact" // HPy version has to use two calls HPy_Type and HPy_Is // It would be faster to check subok first and then exact or subclass check - if (HPy_Is(ctx, HPy_Type(ctx, op), HPyArray_Type) || - (subok && HPy_TypeCheck(ctx, op, HPyArray_Type))) { + array_type = HPyGlobal_Load(ctx, HPyArray_Type); + if (HPy_Is(ctx, HPy_Type(ctx, op), array_type) || + (subok && HPy_TypeCheck(ctx, op, array_type))) { oparr = PyArrayObject_AsStruct(ctx, op); if (HPy_IsNull(type)) { if (copy != NPY_COPY_ALWAYS && STRIDING_OK(oparr, order)) { @@ -1722,7 +1724,7 @@ _hpy_array_fromobject_generic( if (copy == NPY_COPY_NEVER) { HPyErr_SetString(ctx, ctx->h_ValueError, "Unable to avoid copy while creating a new array."); - return HPy_NULL; + goto fail; } ret = HPyArray_NewCopy(ctx, op, order); goto finish; @@ -1740,9 +1742,9 @@ _hpy_array_fromobject_generic( } else { if (copy == NPY_COPY_NEVER) { - PyErr_SetString(PyExc_ValueError, + HPyErr_SetString(ctx, ctx->h_ValueError, "Unable to avoid copy while creating a new array."); - return HPy_NULL; + goto fail; } capi_warn("np.array: PyArray_NewCopy"); PyObject *py_ret = (PyObject *) PyArray_NewCopy(oparr, order); @@ -1768,7 +1770,7 @@ _hpy_array_fromobject_generic( } else if ((order == NPY_FORTRANORDER) /* order == NPY_ANYORDER && */ - || (HPy_TypeCheck(ctx, op, HPyArray_Type) && + || (HPy_TypeCheck(ctx, op, array_type) && PyArray_ISFORTRAN(oparr))) { flags |= NPY_ARRAY_F_CONTIGUOUS; } @@ -1783,6 +1785,8 @@ _hpy_array_fromobject_generic( 0, 0, flags, HPy_NULL); finish: + HPy_Close(ctx, array_type); + if (HPy_IsNull(ret)) { return ret; } @@ -1798,6 +1802,10 @@ _hpy_array_fromobject_generic( // * steals a reference to ret // */ // return _prepend_ones(ret, nd, ndmin, order); + +fail: + HPy_Close(ctx, array_type); + return HPy_NULL; } #undef STRIDING_OK @@ -4921,7 +4929,12 @@ static HPyModuleDef moduledef = { .doc = NULL, .size = -1, .legacy_methods = array_module_methods, - .defines = array_module_hpy_methods + .defines = array_module_hpy_methods, + .globals = { + &HPyArrayDescr_Type, + &HPyArray_Type, + NULL + } }; /* Initialization function for the module */ @@ -5000,7 +5013,8 @@ static HPy init__multiarray_umath_impl(HPyContext *ctx) { // HPY TODO: storing the types to globals to support legacy code, and HPy code w/o module state _PyArrayDescr_Type_p = (PyTypeObject*) HPy_AsPyObject(ctx, h_PyArrayDescr_Type); PyArrayDTypeMeta_Type = (PyTypeObject*) HPy_AsPyObject(ctx, h_PyArrayDTypeMeta_Type); - HPyArrayDescr_Type = HPy_Dup(ctx, h_PyArrayDescr_Type); + + HPyGlobal_Store(ctx, &HPyArrayDescr_Type, h_PyArrayDescr_Type); HPy_Close(ctx, h_PyArrayDTypeMeta_Type); HPy_Close(ctx, h_PyArrayDescr_Type); @@ -5018,7 +5032,7 @@ static HPy init__multiarray_umath_impl(HPyContext *ctx) { goto err; } _PyArray_Type_p = (PyTypeObject*)HPy_AsPyObject(ctx, h_array_type); - HPyArray_Type = HPy_Dup(ctx, h_array_type); + HPyGlobal_Store(ctx, &HPyArray_Type, h_array_type); PyArray_Type.tp_weaklistoffset = offsetof(PyArrayObject_fields, weakreflist); HPy_Close(ctx, h_array_type);