Skip to content

Commit 7c8b125

Browse files
committed
Make cython's array.resize_smart work
1 parent 89a4716 commit 7c8b125

File tree

6 files changed

+200
-2
lines changed

6 files changed

+200
-2
lines changed

graalpython/com.oracle.graal.python.cext/include/listobject.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2018, 2022, Oracle and/or its affiliates.
1+
/* Copyright (c) 2018, 2023, Oracle and/or its affiliates.
22
* Copyright (C) 1996-2017 Python Software Foundation
33
*
44
* Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
@@ -45,6 +45,11 @@ PyAPI_FUNC(int) PyList_Sort(PyObject *);
4545
PyAPI_FUNC(int) PyList_Reverse(PyObject *);
4646
PyAPI_FUNC(PyObject *) PyList_AsTuple(PyObject *);
4747

48+
/*
49+
* GraalPy-specific, used to implement cython's array.resize_smart
50+
*/
51+
PyAPI_FUNC(int) _PyArray_Resize(PyObject* array, Py_ssize_t new_size);
52+
4853
#ifndef Py_LIMITED_API
4954
# define Py_CPYTHON_LISTOBJECT_H
5055
# include "cpython/listobject.h"
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
2+
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3+
#
4+
# The Universal Permissive License (UPL), Version 1.0
5+
#
6+
# Subject to the condition set forth below, permission is hereby granted to any
7+
# person obtaining a copy of this software, associated documentation and/or
8+
# data (collectively the "Software"), free of charge and under any and all
9+
# copyright rights in the Software, and any and all patent rights owned or
10+
# freely licensable by each licensor hereunder covering either (i) the
11+
# unmodified Software as contributed to or provided by such licensor, or (ii)
12+
# the Larger Works (as defined below), to deal in both
13+
#
14+
# (a) the Software, and
15+
#
16+
# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
17+
# one is included with the Software each a "Larger Work" to which the Software
18+
# is contributed by such licensors),
19+
#
20+
# without restriction, including without limitation the rights to copy, create
21+
# derivative works of, display, perform, and distribute the Software and make,
22+
# use, sell, offer for sale, import, export, have made, and have sold the
23+
# Software and the Larger Work(s), and to sublicense the foregoing rights on
24+
# either these or other terms.
25+
#
26+
# This license is subject to the following condition:
27+
#
28+
# The above copyright notice and either this complete permission notice or at a
29+
# minimum a reference to the UPL must be included in all copies or substantial
30+
# portions of the Software.
31+
#
32+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38+
# SOFTWARE.
39+
import sys
40+
from array import array
41+
42+
from tests.cpyext import CPyExtTestCase, CPyExtFunction, unhandled_error_compare
43+
44+
45+
def reference_array_resize(args):
46+
a, n = args
47+
if n < len(a):
48+
del a[n:]
49+
else:
50+
a.extend([0 for i in range(n - len(a))])
51+
return a
52+
53+
54+
class TestPyArray(CPyExtTestCase):
55+
56+
def compile_module(self, name):
57+
type(self).mro()[1].__dict__["test_%s" % name].create_module(name)
58+
super().compile_module(name)
59+
60+
if sys.implementation.name == 'graalpy':
61+
test__PyArray_Resize = CPyExtFunction(
62+
reference_array_resize,
63+
lambda: (
64+
(array('i', [1, 2, 3]), 1),
65+
(array('i'), 3),
66+
),
67+
code="""
68+
PyObject* wrap__PyArray_Resize(PyObject* array, Py_ssize_t new_size) {
69+
if (_PyArray_Resize(array, new_size) < 0)
70+
return NULL;
71+
Py_INCREF(array);
72+
return array;
73+
}
74+
""",
75+
callfunction="wrap__PyArray_Resize",
76+
resultspec="O",
77+
argspec='On',
78+
arguments=["PyObject* array", "Py_ssize_t new_size"],
79+
cmpfunc=unhandled_error_compare,
80+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.graal.python.builtins.modules.cext;
42+
43+
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.MemoryError;
44+
import static com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiCallPath.Direct;
45+
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.Int;
46+
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyObject;
47+
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.Py_ssize_t;
48+
49+
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiBinaryBuiltinNode;
50+
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiBuiltin;
51+
import com.oracle.graal.python.builtins.objects.array.PArray;
52+
import com.oracle.graal.python.util.OverflowException;
53+
import com.oracle.truffle.api.CompilerDirectives;
54+
import com.oracle.truffle.api.dsl.Specialization;
55+
56+
public final class PythonCextArrayBuiltins {
57+
58+
/**
59+
* Graalpy-specific function implemented for Cython
60+
*/
61+
@CApiBuiltin(ret = Int, args = {PyObject, Py_ssize_t}, call = Direct)
62+
abstract static class _PyArray_Resize extends CApiBinaryBuiltinNode {
63+
@Specialization
64+
int resize(PArray object, long newSize) {
65+
try {
66+
object.resize((int) newSize);
67+
} catch (OverflowException e) {
68+
CompilerDirectives.transferToInterpreterAndInvalidate();
69+
throw raise(MemoryError);
70+
}
71+
return 0;
72+
}
73+
}
74+
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiCodeGen.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ public static boolean assertBuiltins(Object capiLibrary) {
550550
"_PyASCIIObject_STATE_COMPACT", "_PyASCIIObject_STATE_KIND", "_PyASCIIObject_STATE_READY", "_PyASCIIObject_WSTR", "_PyByteArray_Start", "_PyEval_SetCoroutineOriginTrackingDepth",
551551
"_PyFrame_SetLineNumber", "_PyMemoryView_GetBuffer", "_PySequence_Fast_ITEMS", "_PySequence_ITEM", "_PyUnicodeObject_DATA", "_PyUnicode_get_wstr_length", "_Py_REFCNT",
552552
"_Py_SET_REFCNT", "_Py_SET_SIZE", "_Py_SET_TYPE", "_Py_SIZE", "_Py_TYPE", "_PyTuple_SET_ITEM", "_PyCFunction_GetModule", "_PyCFunction_GetMethodDef",
553-
"PyCode_GetName", "PyCode_GetFileName", "_PyList_SET_ITEM",
553+
"PyCode_GetName", "PyCode_GetFileName", "_PyList_SET_ITEM", "_PyArray_Resize",
554554
// TODO GR-46546 The following are backports from 3.11. Remove when updating
555555
"PyFrame_GetLasti", "PyFrame_GetLocals", "PyFrame_GetGlobals", "PyFrame_GetBuiltins"};
556556

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiFunction.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@
189189
import java.util.List;
190190

191191
import com.oracle.graal.python.builtins.modules.cext.PythonCextAbstractBuiltins;
192+
import com.oracle.graal.python.builtins.modules.cext.PythonCextArrayBuiltins;
192193
import com.oracle.graal.python.builtins.modules.cext.PythonCextBoolBuiltins;
193194
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins;
194195
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiBuiltin;
@@ -1383,6 +1384,7 @@ static List<CApiBuiltinDesc> getOtherBuiltinDefinitions() {
13831384
static List<CApiBuiltinDesc> getJavaBuiltinDefinitions() {
13841385
ArrayList<CApiBuiltinDesc> result = new ArrayList<>();
13851386
addCApiBuiltins(result, PythonCextAbstractBuiltins.class);
1387+
addCApiBuiltins(result, PythonCextArrayBuiltins.class);
13861388
addCApiBuiltins(result, PythonCextBoolBuiltins.class);
13871389
addCApiBuiltins(result, PythonCextBuiltins.class);
13881390
addCApiBuiltins(result, PythonCextBytesBuiltins.class);

graalpython/lib-graalpython/patches/Cython/Cython-0.29.32.patch

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,3 +268,40 @@ index 98b5e26..0f44675 100644
268268
return PyObject_RichCompareBool(s1, s2, equals);
269269
#else
270270
if (s1 == s2) {
271+
diff --git a/Cython/Utility/arrayarray.h b/Cython/Utility/arrayarray.h
272+
index a9e4923..ac9a2bd 100644
273+
--- a/Cython/Utility/arrayarray.h
274+
+++ b/Cython/Utility/arrayarray.h
275+
@@ -109,6 +109,9 @@ PyObject* newarrayobject(PyTypeObject *type, Py_ssize_t size,
276+
// fast resize (reallocation to the point)
277+
// not designed for filing small increments (but for fast opaque array apps)
278+
static CYTHON_INLINE int resize(arrayobject *self, Py_ssize_t n) {
279+
+#ifdef GRAALVM_PYTHON
280+
+ return _PyArray_Resize((PyObject*)self, n);
281+
+#else
282+
void *items = (void*) self->data.ob_item;
283+
PyMem_Resize(items, char, (size_t)(n * self->ob_descr->itemsize));
284+
if (items == NULL) {
285+
@@ -119,10 +122,14 @@ static CYTHON_INLINE int resize(arrayobject *self, Py_ssize_t n) {
286+
__Pyx_SET_SIZE(self, n);
287+
self->allocated = n;
288+
return 0;
289+
+#endif
290+
}
291+
292+
// suitable for small increments; over allocation 50% ;
293+
static CYTHON_INLINE int resize_smart(arrayobject *self, Py_ssize_t n) {
294+
+#ifdef GRAALVM_PYTHON
295+
+ return _PyArray_Resize((PyObject*)self, n);
296+
+#else
297+
void *items = (void*) self->data.ob_item;
298+
Py_ssize_t newsize;
299+
if (n < self->allocated && n*4 > self->allocated) {
300+
@@ -143,6 +150,7 @@ static CYTHON_INLINE int resize_smart(arrayobject *self, Py_ssize_t n) {
301+
__Pyx_SET_SIZE(self, n);
302+
self->allocated = newsize;
303+
return 0;
304+
+#endif
305+
}
306+
307+
#endif

0 commit comments

Comments
 (0)