|
41 | 41 | package com.oracle.graal.python.builtins.modules.cext; |
42 | 42 |
|
43 | 43 | import static com.oracle.graal.python.builtins.PythonBuiltinClassType.IndexError; |
| 44 | +import static com.oracle.graal.python.builtins.PythonBuiltinClassType.MemoryError; |
44 | 45 | import static com.oracle.graal.python.builtins.PythonBuiltinClassType.SystemError; |
45 | 46 | import static com.oracle.graal.python.builtins.PythonBuiltinClassType.TypeError; |
46 | 47 | import static com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiCallPath.Direct; |
|
68 | 69 | import com.oracle.graal.python.builtins.objects.PNone; |
69 | 70 | import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.EnsurePythonObjectNode; |
70 | 71 | import com.oracle.graal.python.builtins.objects.cext.capi.PySequenceArrayWrapper; |
| 72 | +import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTiming; |
| 73 | +import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions.NativeToPythonInternalNode; |
| 74 | +import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions.PythonToNativeInternalNode; |
71 | 75 | import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.GetItemScalarNode; |
72 | 76 | import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.ListGeneralizationNode; |
73 | 77 | import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.SetItemScalarNode; |
| 78 | +import com.oracle.graal.python.builtins.objects.ints.PInt; |
74 | 79 | import com.oracle.graal.python.builtins.objects.list.ListBuiltins; |
75 | 80 | import com.oracle.graal.python.builtins.objects.list.ListBuiltins.ListExtendNode; |
76 | 81 | import com.oracle.graal.python.builtins.objects.list.ListBuiltins.ListInsertNode; |
|
79 | 84 | import com.oracle.graal.python.lib.PySliceNew; |
80 | 85 | import com.oracle.graal.python.nodes.ErrorMessages; |
81 | 86 | import com.oracle.graal.python.nodes.PRaiseNode; |
82 | | -import com.oracle.graal.python.nodes.builtins.ListNodes.AppendNode; |
| 87 | +import com.oracle.graal.python.nodes.builtins.ListNodes.PListAppendNode; |
83 | 88 | import com.oracle.graal.python.nodes.builtins.TupleNodes.ConstructTupleNode; |
84 | 89 | import com.oracle.graal.python.runtime.PythonContext; |
85 | 90 | import com.oracle.graal.python.runtime.object.PFactory; |
|
95 | 100 |
|
96 | 101 | public final class PythonCextListBuiltins { |
97 | 102 |
|
98 | | - @CApiBuiltin(ret = PyObjectTransfer, args = {Py_ssize_t}, call = Direct) |
99 | | - abstract static class PyList_New extends CApiUnaryBuiltinNode { |
100 | | - @Specialization(guards = "size < 0") |
101 | | - static Object newListError(long size, |
102 | | - @Bind Node inliningTarget) { |
103 | | - throw PRaiseNode.raiseStatic(inliningTarget, SystemError, BAD_ARG_TO_INTERNAL_FUNC_S, size); |
104 | | - } |
105 | | - |
106 | | - @SuppressWarnings("unused") |
107 | | - @Specialization(guards = "size == 0") |
108 | | - static Object newEmptyList(long size, |
109 | | - @Bind PythonLanguage language) { |
110 | | - return PFactory.createList(language); |
111 | | - } |
| 103 | + private static final CApiTiming TIMING_PYLIST_NEW = CApiTiming.create(false, "PyList_New"); |
112 | 104 |
|
113 | | - @Specialization(guards = "size > 0") |
114 | | - static Object newList(long size, |
115 | | - @Bind PythonLanguage language) { |
116 | | - return PFactory.createList(language, array(size)); |
117 | | - } |
| 105 | + @CApiBuiltin(ret = PyObjectTransfer, args = {Py_ssize_t}, call = Direct, acquireGil = false) |
| 106 | + static long PyList_New(long size) { |
| 107 | + CApiTiming.enter(); |
| 108 | + try { |
| 109 | + if (size < 0) { |
| 110 | + throw PRaiseNode.raiseStatic(null, SystemError, BAD_ARG_TO_INTERNAL_FUNC_S, size); |
| 111 | + } |
118 | 112 |
|
119 | | - private static Object[] array(long size) { |
120 | | - Object[] a = new Object[(int) size]; |
121 | | - Arrays.fill(a, PNone.NO_VALUE); |
122 | | - return a; |
| 113 | + PythonLanguage language = PythonLanguage.get(null); |
| 114 | + PList result; |
| 115 | + if (size == 0) { |
| 116 | + result = PFactory.createList(language); |
| 117 | + } else { |
| 118 | + if (!PInt.fitsInInt(size)) { |
| 119 | + throw PRaiseNode.raiseStatic(null, MemoryError); |
| 120 | + } |
| 121 | + Object[] a = new Object[(int) size]; |
| 122 | + Arrays.fill(a, PNone.NO_VALUE); |
| 123 | + result = PFactory.createList(language, a); |
| 124 | + } |
| 125 | + return PythonToNativeInternalNode.executeNewRefUncached(result); |
| 126 | + } finally { |
| 127 | + CApiTiming.exit(TIMING_PYLIST_NEW); |
123 | 128 | } |
124 | 129 | } |
125 | 130 |
|
@@ -157,58 +162,50 @@ Object fallback(Object list, @SuppressWarnings("unused") Object pos) { |
157 | 162 | } |
158 | 163 | } |
159 | 164 |
|
160 | | - @CApiBuiltin(ret = PyObjectTransfer, args = {PyObject, Py_ssize_t}, call = Direct) |
161 | | - abstract static class PyList_GetItemRef extends CApiBinaryBuiltinNode { |
| 165 | + private static final CApiTiming TIMING_PYLIST_GETITEMREF = CApiTiming.create(false, "PyList_GetItemRef"); |
162 | 166 |
|
163 | | - @Specialization |
164 | | - static Object doPList(PList list, long key, |
165 | | - @Bind Node inliningTarget, |
166 | | - @Bind PythonContext context, |
167 | | - @Cached EnsurePythonObjectNode ensureNode, |
168 | | - @Cached ListGeneralizationNode generalizationNode, |
169 | | - @Cached SetItemScalarNode setItemNode, |
170 | | - @Cached GetItemScalarNode getItemNode, |
171 | | - @Cached PRaiseNode raiseNode) { |
| 167 | + @CApiBuiltin(ret = PyObjectTransfer, args = {PyObject, Py_ssize_t}, call = Direct) |
| 168 | + static long PyList_GetItemRef(long opPtr, long key) { |
| 169 | + CApiTiming.enter(); |
| 170 | + try { |
| 171 | + Object op = NativeToPythonInternalNode.executeUncached(opPtr, false); |
| 172 | + if (!(op instanceof PList list)) { |
| 173 | + throw PRaiseNode.raiseStatic(null, TypeError, ErrorMessages.EXPECTED_A_LIST); |
| 174 | + } |
172 | 175 | SequenceStorage sequenceStorage = list.getSequenceStorage(); |
173 | 176 | // we must do a bounds-check but we must not normalize the index |
174 | 177 | if (key < 0 || key >= sequenceStorage.length()) { |
175 | | - throw raiseNode.raise(inliningTarget, IndexError, ErrorMessages.LIST_INDEX_OUT_OF_RANGE); |
| 178 | + throw PRaiseNode.raiseStatic(null, IndexError, ErrorMessages.LIST_INDEX_OUT_OF_RANGE); |
176 | 179 | } |
177 | | - Object result = getItemNode.execute(inliningTarget, sequenceStorage, (int) key); |
| 180 | + Object result = GetItemScalarNode.executeUncached(sequenceStorage, (int) key); |
178 | 181 | // See the note in PyDict_GetItemRef |
179 | | - Object promotedValue = ensureNode.execute(context, result, false); |
| 182 | + Object promotedValue = EnsurePythonObjectNode.executeUncached(PythonContext.get(null), result, false); |
180 | 183 | if (promotedValue != result) { |
181 | | - sequenceStorage = generalizationNode.execute(inliningTarget, sequenceStorage, promotedValue); |
| 184 | + sequenceStorage = ListGeneralizationNode.executeUncached(sequenceStorage, promotedValue); |
182 | 185 | list.setSequenceStorage(sequenceStorage); |
183 | | - setItemNode.execute(inliningTarget, sequenceStorage, (int) key, promotedValue); |
184 | | - return promotedValue; |
| 186 | + SetItemScalarNode.executeUncached(sequenceStorage, (int) key, promotedValue); |
185 | 187 | } |
186 | | - return result; |
187 | | - } |
188 | | - |
189 | | - @Fallback |
190 | | - static Object fallback(@SuppressWarnings("unused") Object list, @SuppressWarnings("unused") Object pos, |
191 | | - @Bind Node inliningTarget) { |
192 | | - throw PRaiseNode.raiseStatic(inliningTarget, TypeError, ErrorMessages.EXPECTED_A_LIST); |
| 188 | + return PythonToNativeInternalNode.executeNewRefUncached(promotedValue); |
| 189 | + } finally { |
| 190 | + CApiTiming.exit(TIMING_PYLIST_GETITEMREF); |
193 | 191 | } |
194 | 192 | } |
195 | 193 |
|
196 | | - @CApiBuiltin(ret = Int, args = {PyObject, PyObject}, call = Direct) |
197 | | - abstract static class PyList_Append extends CApiBinaryBuiltinNode { |
| 194 | + private static final CApiTiming TIMING_PYLIST_APPEND = CApiTiming.create(false, "PyList_Append"); |
198 | 195 |
|
199 | | - @Specialization |
200 | | - int append(PList list, Object newItem, |
201 | | - @Cached AppendNode appendNode) { |
202 | | - if (newItem == PNone.NO_VALUE) { |
203 | | - throw badInternalCall("newitem"); |
| 196 | + @CApiBuiltin(ret = Int, args = {PyObject, PyObject}, call = Direct) |
| 197 | + static int PyList_Append(long opPtr, long itemPtr) { |
| 198 | + CApiTiming.enter(); |
| 199 | + try { |
| 200 | + Object op = NativeToPythonInternalNode.executeUncached(opPtr, false); |
| 201 | + Object item = NativeToPythonInternalNode.executeUncached(itemPtr, false); |
| 202 | + if (op instanceof PList list && item != PNone.NO_VALUE) { |
| 203 | + PListAppendNode.executeUncached(list, item); |
| 204 | + return 0; |
204 | 205 | } |
205 | | - appendNode.execute(list, newItem); |
206 | | - return 0; |
207 | | - } |
208 | | - |
209 | | - @Fallback |
210 | | - int fallback(Object list, @SuppressWarnings("unused") Object newItem) { |
211 | | - throw raiseFallback(list, PythonBuiltinClassType.PList); |
| 206 | + throw PythonCextBuiltins.badInternalCall("PyList_Append", "op"); |
| 207 | + } finally { |
| 208 | + CApiTiming.exit(TIMING_PYLIST_APPEND); |
212 | 209 | } |
213 | 210 | } |
214 | 211 |
|
@@ -293,21 +290,23 @@ Object fallback(Object list, @SuppressWarnings("unused") Object iterable) { |
293 | 290 | } |
294 | 291 | } |
295 | 292 |
|
| 293 | + private static final CApiTiming TIMING_PYLIST_SIZE = CApiTiming.create(false, "PyList_Size"); |
| 294 | + |
296 | 295 | /* |
297 | 296 | * A pure-C Py_SIZE implementation regressed mixed managed/native/list-subclass workload by |
298 | 297 | * about 1.26x. |
299 | 298 | */ |
300 | | - @CApiBuiltin(ret = Py_ssize_t, args = {PyObject}, call = Direct) |
301 | | - abstract static class PyList_Size extends CApiUnaryBuiltinNode { |
302 | | - |
303 | | - @Specialization |
304 | | - static long size(PList list) { |
305 | | - return list.getSequenceStorage().length(); |
306 | | - } |
307 | | - |
308 | | - @Fallback |
309 | | - long fallback(Object list) { |
310 | | - throw raiseFallback(list, PythonBuiltinClassType.PList); |
| 299 | + @CApiBuiltin(ret = Py_ssize_t, args = {PyObject}, call = Direct, acquireGil = false) |
| 300 | + static long PyList_Size(long opPtr) { |
| 301 | + CApiTiming.enter(); |
| 302 | + try { |
| 303 | + Object op = NativeToPythonInternalNode.executeUncached(opPtr, false); |
| 304 | + if (op instanceof PList list) { |
| 305 | + return list.getSequenceStorage().length(); |
| 306 | + } |
| 307 | + throw PythonCextBuiltins.badInternalCall("PyList_Size", "op"); |
| 308 | + } finally { |
| 309 | + CApiTiming.exit(TIMING_PYLIST_SIZE); |
311 | 310 | } |
312 | 311 | } |
313 | 312 |
|
|
0 commit comments