Skip to content

Commit

Permalink
Pull request #12: Use HPyGlobal for global type vars
Browse files Browse the repository at this point in the history
Merge in ~STEPAN.SINDELAR_ORACLE.COM/numpy-hpy from fa/hpy_global to labs-hpy-port

* commit '4f2d3de9229a9c7d2ae6a978cda04ab2262209a8':
  Use HPyGlobal for global type vars
  • Loading branch information
fangerer committed Mar 23, 2022
2 parents 404a43d + 4f2d3de commit 10ae760
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 31 deletions.
31 changes: 28 additions & 3 deletions numpy/core/include/numpy/ndarrayobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) || \
Expand Down
1 change: 0 additions & 1 deletion numpy/core/include/numpy/ndarraytypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
3 changes: 2 additions & 1 deletion numpy/core/src/multiarray/arrayobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
26 changes: 14 additions & 12 deletions numpy/core/src/multiarray/ctors.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -977,6 +980,8 @@ HPyArray_NewFromDescr_int(
}
}
}
} else {
HPy_Close(ctx, array_type);
}
return result;

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions numpy/core/src/multiarray/descriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_ */
38 changes: 26 additions & 12 deletions numpy/core/src/multiarray/multiarraymodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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)) {
Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
Expand All @@ -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);

Expand Down

0 comments on commit 10ae760

Please sign in to comment.