|
145 | 145 | import com.oracle.graal.python.nodes.argument.ReadIndexedArgumentNode; |
146 | 146 | import com.oracle.graal.python.nodes.argument.ReadVarArgsNode; |
147 | 147 | import com.oracle.graal.python.nodes.argument.ReadVarKeywordsNode; |
| 148 | +import com.oracle.graal.python.nodes.argument.keywords.ExecuteKeywordStarargsNode.ExpandKeywordStarargsNode; |
| 149 | +import com.oracle.graal.python.nodes.argument.positional.ExecutePositionalStarargsNode; |
148 | 150 | import com.oracle.graal.python.nodes.attributes.HasInheritedAttributeNode; |
149 | 151 | import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode; |
150 | 152 | import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; |
151 | 153 | import com.oracle.graal.python.nodes.attributes.WriteAttributeToDynamicObjectNode; |
152 | 154 | import com.oracle.graal.python.nodes.attributes.WriteAttributeToObjectNode; |
| 155 | +import com.oracle.graal.python.nodes.call.CallNode; |
153 | 156 | import com.oracle.graal.python.nodes.call.InvokeNode; |
154 | 157 | import com.oracle.graal.python.nodes.call.PythonCallNode; |
155 | 158 | import com.oracle.graal.python.nodes.call.special.LookupAndCallBinaryNode; |
|
199 | 202 | import com.oracle.truffle.api.dsl.GenerateNodeFactory; |
200 | 203 | import com.oracle.truffle.api.dsl.ImportStatic; |
201 | 204 | import com.oracle.truffle.api.dsl.NodeFactory; |
| 205 | +import com.oracle.truffle.api.dsl.ReportPolymorphism; |
202 | 206 | import com.oracle.truffle.api.dsl.Specialization; |
203 | 207 | import com.oracle.truffle.api.dsl.TypeSystemReference; |
204 | 208 | import com.oracle.truffle.api.frame.VirtualFrame; |
@@ -2768,4 +2772,104 @@ private CoderResult decode(CharBuffer resultBuffer, ByteBuffer inputBuffer, Stri |
2768 | 2772 | return decoder.onMalformedInput(CodingErrorAction.REPORT).onUnmappableCharacter(action).decode(inputBuffer, resultBuffer, true); |
2769 | 2773 | } |
2770 | 2774 | } |
| 2775 | + |
| 2776 | + @Builtin(name = "PyObject_Call", parameterNames = {"callee", "args", "kwargs"}) |
| 2777 | + @GenerateNodeFactory |
| 2778 | + @ReportPolymorphism |
| 2779 | + abstract static class PyObjectCallNode extends PythonTernaryBuiltinNode { |
| 2780 | + |
| 2781 | + @Specialization(guards = "kwargsLib.isNull(kwargsObj)") |
| 2782 | + Object doNoKeywords(VirtualFrame frame, Object callableObj, Object argsObj, @SuppressWarnings("unused") Object kwargsObj, |
| 2783 | + @CachedLibrary(limit = "3") @SuppressWarnings("unused") InteropLibrary kwargsLib, |
| 2784 | + @Shared("expandArgsNode") @Cached ExecutePositionalStarargsNode expandArgsNode, |
| 2785 | + @Shared("callableToJavaNode") @Cached CExtNodes.AsPythonObjectNode callableToJavaNode, |
| 2786 | + @Cached CExtNodes.AsPythonObjectNode argsToJavaNode, |
| 2787 | + @Shared("toSulongNode") @Cached CExtNodes.ToSulongNode toSulongNode, |
| 2788 | + @Shared("callNodeNoKeywords") @Cached CallNode callNode, |
| 2789 | + @Cached GetNativeNullNode getNativeNullNode, |
| 2790 | + @Shared("nullToSulongNode") @Cached CExtNodes.ToSulongNode nullToSulongNode) { |
| 2791 | + try { |
| 2792 | + Object callable = callableToJavaNode.execute(callableObj); |
| 2793 | + Object[] args = expandArgsNode.executeWith(frame, argsToJavaNode.execute(argsObj)); |
| 2794 | + return toSulongNode.execute(callNode.execute(frame, callable, args, PKeyword.EMPTY_KEYWORDS)); |
| 2795 | + } catch (PException e) { |
| 2796 | + // getContext() acts as a branch profile |
| 2797 | + NativeBuiltin.transformToNative(getContext(), PArguments.getCurrentFrameInfo(frame), e); |
| 2798 | + return nullToSulongNode.execute(getNativeNullNode.execute()); |
| 2799 | + } |
| 2800 | + } |
| 2801 | + |
| 2802 | + @Specialization(guards = {"!kwargsLib.isNull(kwargsObj)", "isEmptyDict(kwargsToJavaNode, lenNode, kwargsObj)"}, limit = "1") |
| 2803 | + Object doEmptyKeywords(VirtualFrame frame, Object callableObj, Object argsObj, @SuppressWarnings("unused") Object kwargsObj, |
| 2804 | + @CachedLibrary(limit = "3") @SuppressWarnings("unused") InteropLibrary kwargsLib, |
| 2805 | + @Shared("expandArgsNode") @Cached ExecutePositionalStarargsNode expandArgsNode, |
| 2806 | + @Shared("callableToJavaNode") @Cached CExtNodes.AsPythonObjectNode callableToJavaNode, |
| 2807 | + @Cached CExtNodes.AsPythonObjectNode argsToJavaNode, |
| 2808 | + @Cached CExtNodes.AsPythonObjectNode kwargsToJavaNode, |
| 2809 | + @Cached HashingCollectionNodes.LenNode lenNode, |
| 2810 | + @Shared("toSulongNode") @Cached CExtNodes.ToSulongNode toSulongNode, |
| 2811 | + @Shared("callNodeNoKeywords") @Cached CallNode callNode, |
| 2812 | + @Cached GetNativeNullNode getNativeNullNode, |
| 2813 | + @Shared("nullToSulongNode") @Cached CExtNodes.ToSulongNode nullToSulongNode) { |
| 2814 | + try { |
| 2815 | + Object callable = callableToJavaNode.execute(callableObj); |
| 2816 | + Object[] args = expandArgsNode.executeWith(frame, argsToJavaNode.execute(argsObj)); |
| 2817 | + return toSulongNode.execute(callNode.execute(frame, callable, args, PKeyword.EMPTY_KEYWORDS)); |
| 2818 | + } catch (PException e) { |
| 2819 | + // getContext() acts as a branch profile |
| 2820 | + NativeBuiltin.transformToNative(getContext(), PArguments.getCurrentFrameInfo(frame), e); |
| 2821 | + return nullToSulongNode.execute(getNativeNullNode.execute()); |
| 2822 | + } |
| 2823 | + } |
| 2824 | + |
| 2825 | + @Specialization(replaces = {"doNoKeywords", "doEmptyKeywords"}) |
| 2826 | + Object doGeneric(VirtualFrame frame, Object callableObj, Object argsObj, Object kwargsObj, |
| 2827 | + @CachedLibrary(limit = "3") @SuppressWarnings("unused") InteropLibrary argsLib, |
| 2828 | + @CachedLibrary(limit = "3") @SuppressWarnings("unused") InteropLibrary kwargsLib, |
| 2829 | + @Shared("expandArgsNode") @Cached ExecutePositionalStarargsNode expandArgsNode, |
| 2830 | + @Cached ExpandKeywordStarargsNode expandKwargsNode, |
| 2831 | + @Shared("callableToJavaNode") @Cached CExtNodes.AsPythonObjectNode callableToJavaNode, |
| 2832 | + @Cached CExtNodes.AsPythonObjectNode argsToJavaNode, |
| 2833 | + @Cached CExtNodes.AsPythonObjectNode kwargsToJavaNode, |
| 2834 | + @Cached("createBinaryProfile()") ConditionProfile argsIsNullProfile, |
| 2835 | + @Cached("createBinaryProfile()") ConditionProfile kwargsIsNullProfile, |
| 2836 | + @Exclusive @Cached CallNode callNode, |
| 2837 | + @Shared("toSulongNode") @Cached CExtNodes.ToSulongNode toSulongNode, |
| 2838 | + @Cached GetNativeNullNode getNativeNullNode, |
| 2839 | + @Shared("nullToSulongNode") @Cached CExtNodes.ToSulongNode nullToSulongNode) { |
| 2840 | + try { |
| 2841 | + Object callable = callableToJavaNode.execute(callableObj); |
| 2842 | + Object[] args; |
| 2843 | + PKeyword[] keywords; |
| 2844 | + |
| 2845 | + // expand positional arguments |
| 2846 | + if (argsIsNullProfile.profile(argsLib.isNull(argsObj))) { |
| 2847 | + args = new Object[0]; |
| 2848 | + } else { |
| 2849 | + args = expandArgsNode.executeWith(frame, argsToJavaNode.execute(argsObj)); |
| 2850 | + } |
| 2851 | + |
| 2852 | + // expand keywords |
| 2853 | + if (kwargsIsNullProfile.profile(kwargsLib.isNull(kwargsObj))) { |
| 2854 | + keywords = PKeyword.EMPTY_KEYWORDS; |
| 2855 | + } else { |
| 2856 | + keywords = expandKwargsNode.executeWith(kwargsToJavaNode.execute(kwargsObj)); |
| 2857 | + } |
| 2858 | + return toSulongNode.execute(callNode.execute(frame, callable, args, keywords)); |
| 2859 | + } catch (PException e) { |
| 2860 | + // getContext() acts as a branch profile |
| 2861 | + NativeBuiltin.transformToNative(getContext(), PArguments.getCurrentFrameInfo(frame), e); |
| 2862 | + return nullToSulongNode.execute(getNativeNullNode.execute()); |
| 2863 | + } |
| 2864 | + } |
| 2865 | + |
| 2866 | + static boolean isEmptyDict(CExtNodes.AsPythonObjectNode asPythonObjectNode, HashingCollectionNodes.LenNode lenNode, Object kwargsObj) { |
| 2867 | + Object unwrapped = asPythonObjectNode.execute(kwargsObj); |
| 2868 | + if (unwrapped instanceof PDict) { |
| 2869 | + return lenNode.execute((PDict) unwrapped) == 0; |
| 2870 | + } |
| 2871 | + return false; |
| 2872 | + } |
| 2873 | + |
| 2874 | + } |
2771 | 2875 | } |
0 commit comments