|
212 | 212 | import com.oracle.graal.python.nodes.WriteUnraisableNode;
|
213 | 213 | import com.oracle.graal.python.nodes.argument.keywords.ExpandKeywordStarargsNode;
|
214 | 214 | import com.oracle.graal.python.nodes.argument.positional.ExecutePositionalStarargsNode;
|
| 215 | +import com.oracle.graal.python.nodes.attributes.GetAttributeNode.GetAnyAttributeNode; |
215 | 216 | import com.oracle.graal.python.nodes.attributes.HasInheritedAttributeNode;
|
216 | 217 | import com.oracle.graal.python.nodes.attributes.LookupInheritedAttributeNode;
|
217 | 218 | import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode;
|
|
229 | 230 | import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
|
230 | 231 | import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
|
231 | 232 | import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
|
| 233 | +import com.oracle.graal.python.nodes.function.builtins.PythonQuaternaryBuiltinNode; |
232 | 234 | import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
|
233 | 235 | import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
|
234 | 236 | import com.oracle.graal.python.nodes.function.builtins.PythonVarargsBuiltinNode;
|
@@ -3300,56 +3302,125 @@ static Object doGeneric(VirtualFrame frame, Object callableObj, Object argsObj,
|
3300 | 3302 | abstract static class PyObjectCallFunctionObjArgsNode extends PythonBinaryBuiltinNode {
|
3301 | 3303 |
|
3302 | 3304 | @Specialization(limit = "1")
|
3303 |
| - static Object doGeneric(VirtualFrame frame, Object callableObj, Object vaList, |
| 3305 | + static Object doFunction(VirtualFrame frame, Object callableObj, Object vaList, |
3304 | 3306 | @CachedLibrary("vaList") InteropLibrary argsArrayLib,
|
3305 |
| - @CachedLibrary(limit = "2") InteropLibrary argLib, |
| 3307 | + @Shared("argLib") @CachedLibrary(limit = "2") InteropLibrary argLib, |
| 3308 | + @CachedLibrary(limit = "1") PythonObjectLibrary callableLib, |
3306 | 3309 | @Cached AsPythonObjectNode asPythonObjectNode,
|
3307 |
| - @Cached CallNode callNode, |
3308 | 3310 | @Cached ToNewRefNode toNewRefNode,
|
3309 | 3311 | @Cached GetNativeNullNode getNativeNullNode,
|
3310 | 3312 | @Cached CExtNodes.ToSulongNode nullToSulongNode,
|
3311 | 3313 | @Cached TransformExceptionToNativeNode transformExceptionToNativeNode) {
|
| 3314 | + try { |
| 3315 | + Object callable = asPythonObjectNode.execute(callableObj); |
| 3316 | + return toNewRefNode.execute(callFunction(frame, callable, vaList, argsArrayLib, argLib, callableLib, asPythonObjectNode)); |
| 3317 | + } catch (PException e) { |
| 3318 | + // transformExceptionToNativeNode acts as a branch profile |
| 3319 | + transformExceptionToNativeNode.execute(frame, e); |
| 3320 | + return nullToSulongNode.execute(getNativeNullNode.execute()); |
| 3321 | + } |
| 3322 | + } |
| 3323 | + |
| 3324 | + static Object callFunction(VirtualFrame frame, Object callable, Object vaList, |
| 3325 | + InteropLibrary argsArrayLib, |
| 3326 | + InteropLibrary argLib, |
| 3327 | + PythonObjectLibrary callableLib, |
| 3328 | + AsPythonObjectNode asPythonObjectNode) { |
3312 | 3329 | if (argsArrayLib.hasArrayElements(vaList)) {
|
3313 | 3330 | try {
|
3314 |
| - try { |
3315 |
| - /* |
3316 |
| - * Function 'PyObject_CallFunctionObjArgs' expects a va_list that contains |
3317 |
| - * just 'PyObject *' and is terminated by 'NULL'. Hence, we allocate an |
3318 |
| - * argument array with one element less than the va_list object says (since |
3319 |
| - * the last element is expected to be 'NULL'; this is best effort). However, |
3320 |
| - * we must also stop at the first 'NULL' element we encounter since a user |
3321 |
| - * could pass several 'NULL'. |
3322 |
| - */ |
3323 |
| - long arraySize = argsArrayLib.getArraySize(vaList); |
3324 |
| - Object[] args = new Object[PInt.intValueExact(arraySize) - 1]; |
3325 |
| - for (int i = 0; i < args.length; i++) { |
3326 |
| - try { |
3327 |
| - Object object = argsArrayLib.readArrayElement(vaList, i); |
3328 |
| - if (argLib.isNull(object)) { |
3329 |
| - break; |
3330 |
| - } |
3331 |
| - args[i] = asPythonObjectNode.execute(object); |
3332 |
| - } catch (InvalidArrayIndexException e) { |
3333 |
| - throw CompilerDirectives.shouldNotReachHere(); |
| 3331 | + /* |
| 3332 | + * Function 'PyObject_CallFunctionObjArgs' expects a va_list that contains just |
| 3333 | + * 'PyObject *' and is terminated by 'NULL'. Hence, we allocate an argument |
| 3334 | + * array with one element less than the va_list object says (since the last |
| 3335 | + * element is expected to be 'NULL'; this is best effort). However, we must also |
| 3336 | + * stop at the first 'NULL' element we encounter since a user could pass several |
| 3337 | + * 'NULL'. |
| 3338 | + */ |
| 3339 | + long arraySize = argsArrayLib.getArraySize(vaList); |
| 3340 | + Object[] args = new Object[PInt.intValueExact(arraySize) - 1]; |
| 3341 | + for (int i = 0; i < args.length; i++) { |
| 3342 | + try { |
| 3343 | + Object object = argsArrayLib.readArrayElement(vaList, i); |
| 3344 | + if (argLib.isNull(object)) { |
| 3345 | + break; |
3334 | 3346 | }
|
| 3347 | + args[i] = asPythonObjectNode.execute(object); |
| 3348 | + } catch (InvalidArrayIndexException e) { |
| 3349 | + throw CompilerDirectives.shouldNotReachHere(); |
3335 | 3350 | }
|
3336 |
| - Object callable = asPythonObjectNode.execute(callableObj); |
3337 |
| - return toNewRefNode.execute(callNode.execute(frame, callable, args, PKeyword.EMPTY_KEYWORDS)); |
3338 |
| - } catch (UnsupportedMessageException | OverflowException e) { |
3339 |
| - // I think we can just assume that there won't be more than |
3340 |
| - // Integer.MAX_VALUE arguments. |
3341 |
| - throw CompilerDirectives.shouldNotReachHere(); |
3342 | 3351 | }
|
3343 |
| - } catch (PException e) { |
3344 |
| - // transformExceptionToNativeNode acts as a branch profile |
3345 |
| - transformExceptionToNativeNode.execute(frame, e); |
3346 |
| - return nullToSulongNode.execute(getNativeNullNode.execute()); |
| 3352 | + return callableLib.callObject(callable, frame, args); |
| 3353 | + } catch (UnsupportedMessageException | OverflowException e) { |
| 3354 | + // I think we can just assume that there won't be more than |
| 3355 | + // Integer.MAX_VALUE arguments. |
| 3356 | + throw CompilerDirectives.shouldNotReachHere(); |
3347 | 3357 | }
|
3348 | 3358 | }
|
3349 | 3359 | throw CompilerDirectives.shouldNotReachHere();
|
3350 | 3360 | }
|
3351 | 3361 | }
|
3352 | 3362 |
|
| 3363 | + // directly called without landing function |
| 3364 | + @Builtin(name = "PyObject_CallMethodObjArgs", parameterNames = {"receiver", "method_name", "va_list"}) |
| 3365 | + @GenerateNodeFactory |
| 3366 | + abstract static class PyObjectCallMethodObjArgsNode extends PythonTernaryBuiltinNode { |
| 3367 | + |
| 3368 | + @Specialization(limit = "1") |
| 3369 | + static Object doMethod(VirtualFrame frame, Object receiverObj, Object methodNameObj, Object vaList, |
| 3370 | + @CachedLibrary(limit = "1") PythonObjectLibrary methodLib, |
| 3371 | + @CachedLibrary("vaList") InteropLibrary argsArrayLib, |
| 3372 | + @Shared("argLib") @CachedLibrary(limit = "2") InteropLibrary argLib, |
| 3373 | + @Cached GetAnyAttributeNode getAnyAttributeNode, |
| 3374 | + @Cached AsPythonObjectNode asPythonObjectNode, |
| 3375 | + @Cached ToNewRefNode toNewRefNode, |
| 3376 | + @Cached GetNativeNullNode getNativeNullNode, |
| 3377 | + @Cached CExtNodes.ToSulongNode nullToSulongNode, |
| 3378 | + @Cached TransformExceptionToNativeNode transformExceptionToNativeNode) { |
| 3379 | + |
| 3380 | + try { |
| 3381 | + Object receiver = asPythonObjectNode.execute(receiverObj); |
| 3382 | + Object methodName = asPythonObjectNode.execute(methodNameObj); |
| 3383 | + Object method = getAnyAttributeNode.executeObject(frame, receiver, methodName); |
| 3384 | + return toNewRefNode.execute(PyObjectCallFunctionObjArgsNode.callFunction(frame, method, vaList, argsArrayLib, argLib, methodLib, asPythonObjectNode)); |
| 3385 | + } catch (PException e) { |
| 3386 | + // transformExceptionToNativeNode acts as a branch profile |
| 3387 | + transformExceptionToNativeNode.execute(frame, e); |
| 3388 | + return nullToSulongNode.execute(getNativeNullNode.execute()); |
| 3389 | + } |
| 3390 | + } |
| 3391 | + } |
| 3392 | + |
| 3393 | + // directly called without landing function |
| 3394 | + @Builtin(name = "PyObject_CallMethod", parameterNames = {"object", "method_name", "args", "single_arg"}) |
| 3395 | + @GenerateNodeFactory |
| 3396 | + abstract static class PyObjectCallMethodNode extends PythonQuaternaryBuiltinNode { |
| 3397 | + @Specialization |
| 3398 | + static Object doGeneric(VirtualFrame frame, Object receiverObj, String methodName, Object argsObj, int singleArg, |
| 3399 | + @CachedLibrary(limit = "1") PythonObjectLibrary objectLib, |
| 3400 | + @Cached AsPythonObjectNode asPythonObjectNode, |
| 3401 | + @Cached CastArgsNode castArgsNode, |
| 3402 | + @Cached ToNewRefNode toNewRefNode, |
| 3403 | + @Cached GetNativeNullNode getNativeNullNode, |
| 3404 | + @Cached CExtNodes.ToSulongNode nullToSulongNode, |
| 3405 | + @Cached TransformExceptionToNativeNode transformExceptionToNativeNode) { |
| 3406 | + |
| 3407 | + try { |
| 3408 | + Object receiver = asPythonObjectNode.execute(receiverObj); |
| 3409 | + Object[] args; |
| 3410 | + if (singleArg != 0) { |
| 3411 | + args = new Object[]{asPythonObjectNode.execute(argsObj)}; |
| 3412 | + } else { |
| 3413 | + args = castArgsNode.execute(frame, argsObj); |
| 3414 | + } |
| 3415 | + return toNewRefNode.execute(objectLib.lookupAndCallRegularMethod(receiver, frame, methodName, args)); |
| 3416 | + } catch (PException e) { |
| 3417 | + // transformExceptionToNativeNode acts as a branch profile |
| 3418 | + transformExceptionToNativeNode.execute(frame, e); |
| 3419 | + return nullToSulongNode.execute(getNativeNullNode.execute()); |
| 3420 | + } |
| 3421 | + } |
| 3422 | + } |
| 3423 | + |
3353 | 3424 | // directly called without landing function
|
3354 | 3425 | @Builtin(name = "PyObject_FastCallDict", parameterNames = {"callable", "argsArray", "kwargs"})
|
3355 | 3426 | @GenerateNodeFactory
|
|
0 commit comments