|
159 | 159 | import com.oracle.graal.python.builtins.objects.list.PList; |
160 | 160 | import com.oracle.graal.python.builtins.objects.module.PythonModule; |
161 | 161 | import com.oracle.graal.python.builtins.objects.object.ObjectNodes; |
162 | | -import com.oracle.graal.python.builtins.objects.object.PythonObject; |
163 | 162 | import com.oracle.graal.python.builtins.objects.tuple.PTuple; |
164 | 163 | import com.oracle.graal.python.builtins.objects.type.SpecialMethodSlot; |
165 | 164 | import com.oracle.graal.python.builtins.objects.type.TpSlots; |
@@ -785,194 +784,116 @@ static Object doObject(VirtualFrame frame, Object a, Object b, |
785 | 784 | } |
786 | 785 | } |
787 | 786 |
|
788 | | - // eval(expression, globals=None, locals=None) |
789 | | - @Builtin(name = J_EVAL, minNumOfPositionalArgs = 1, parameterNames = {"expression", "globals", "locals"}) |
790 | | - @GenerateNodeFactory |
791 | | - public abstract static class EvalNode extends PythonBuiltinNode { |
792 | | - @Child protected CompileNode compileNode; |
793 | | - @Child private GetOrCreateDictNode getOrCreateDictNode; |
794 | | - |
795 | | - final void assertNoFreeVars(Node inliningTarget, PCode code, PRaiseNode raiseNode) { |
796 | | - Object[] freeVars = code.getFreeVars(); |
797 | | - if (freeVars.length > 0) { |
798 | | - throw raiseNode.raise(inliningTarget, PythonBuiltinClassType.TypeError, ErrorMessages.CODE_OBJ_NO_FREE_VARIABLES, getMode()); |
799 | | - } |
800 | | - } |
801 | | - |
802 | | - protected TruffleString getMode() { |
803 | | - return T_EVAL; |
804 | | - } |
805 | | - |
806 | | - static boolean isMapping(Node inliningTarget, PyMappingCheckNode mappingCheckNode, Object object) { |
807 | | - return mappingCheckNode.execute(inliningTarget, object); |
808 | | - } |
809 | | - |
810 | | - static boolean isAnyNone(Object object) { |
811 | | - return object instanceof PNone; |
812 | | - } |
813 | | - |
814 | | - final PCode createAndCheckCode(VirtualFrame frame, Node inliningTarget, Object source, PRaiseNode raiseNode) { |
815 | | - PCode code = getCompileNode().compile(frame, source, T_STRING_SOURCE, getMode(), -1, -1); |
816 | | - assertNoFreeVars(inliningTarget, code, raiseNode); |
817 | | - return code; |
818 | | - } |
819 | | - |
820 | | - private static void inheritGlobals(PFrame callerFrame, Object[] args) { |
821 | | - PArguments.setGlobals(args, callerFrame.getGlobals()); |
822 | | - } |
823 | | - |
824 | | - private static void inheritLocals(Node inliningTarget, PFrame callerFrame, Object[] args, GetFrameLocalsNode getFrameLocalsNode) { |
825 | | - Object callerLocals = getFrameLocalsNode.execute(inliningTarget, callerFrame); |
826 | | - setCustomLocals(args, callerLocals); |
827 | | - } |
828 | | - |
829 | | - private static void setCustomLocals(Object[] args, Object locals) { |
830 | | - PArguments.setSpecialArgument(args, locals); |
831 | | - } |
832 | | - |
833 | | - private void setBuiltinsInGlobals(VirtualFrame frame, Node inliningTarget, PDict globals, HashingCollectionNodes.SetItemNode setBuiltins, PythonModule builtins) { |
834 | | - if (builtins != null) { |
835 | | - PDict builtinsDict = getOrCreateDictNode(builtins); |
836 | | - setBuiltins.execute(frame, inliningTarget, globals, T___BUILTINS__, builtinsDict); |
837 | | - } else { |
838 | | - // This happens during context initialization |
839 | | - return; |
840 | | - } |
841 | | - } |
842 | | - |
843 | | - private void setCustomGlobals(VirtualFrame frame, Node inliningTarget, PDict globals, HashingCollectionNodes.SetItemNode setBuiltins, Object[] args) { |
844 | | - PythonModule builtins = getContext().getBuiltins(); |
845 | | - setBuiltinsInGlobals(frame, inliningTarget, globals, setBuiltins, builtins); |
846 | | - PArguments.setGlobals(args, globals); |
847 | | - } |
| 787 | + @GenerateInline |
| 788 | + @GenerateCached(false) |
| 789 | + abstract static class CreateEvalExecArgumentsNode extends Node { |
| 790 | + public abstract Object[] execute(VirtualFrame frame, Node inliningTarget, Object globals, Object locals, TruffleString mode); |
848 | 791 |
|
849 | 792 | @Specialization |
850 | | - @SuppressWarnings("truffle-static-method") |
851 | | - Object execInheritGlobalsInheritLocals(VirtualFrame frame, Object source, @SuppressWarnings("unused") PNone globals, @SuppressWarnings("unused") PNone locals, |
852 | | - @Bind("this") Node inliningTarget, |
| 793 | + static Object[] inheritGlobals(VirtualFrame frame, Node inliningTarget, @SuppressWarnings("unused") PNone globals, Object locals, TruffleString mode, |
853 | 794 | @Exclusive @Cached ReadCallerFrameNode readCallerFrameNode, |
854 | | - @Exclusive @Cached CodeNodes.GetCodeCallTargetNode getCt, |
855 | | - @Cached GetFrameLocalsNode getFrameLocalsNode, |
856 | | - @Shared @Cached CallDispatchers.SimpleIndirectInvokeNode invoke, |
| 795 | + @Exclusive @Cached InlinedConditionProfile haveLocals, |
| 796 | + @Exclusive @Cached PyMappingCheckNode mappingCheckNode, |
| 797 | + @Exclusive @Cached GetFrameLocalsNode getFrameLocalsNode, |
857 | 798 | @Exclusive @Cached PRaiseNode raiseNode) { |
858 | | - PCode code = createAndCheckCode(frame, inliningTarget, source, raiseNode); |
859 | 799 | PFrame callerFrame = readCallerFrameNode.executeWith(frame, 0); |
860 | 800 | Object[] args = PArguments.create(); |
861 | | - inheritGlobals(callerFrame, args); |
862 | | - inheritLocals(inliningTarget, callerFrame, args, getFrameLocalsNode); |
863 | | - |
864 | | - return invoke.execute(frame, inliningTarget, getCt.execute(inliningTarget, code), args); |
| 801 | + PArguments.setGlobals(args, callerFrame.getGlobals()); |
| 802 | + if (haveLocals.profile(inliningTarget, locals instanceof PNone)) { |
| 803 | + Object callerLocals = getFrameLocalsNode.execute(inliningTarget, callerFrame); |
| 804 | + setCustomLocals(args, callerLocals); |
| 805 | + } else { |
| 806 | + if (!mappingCheckNode.execute(inliningTarget, locals)) { |
| 807 | + throw raiseNode.raise(inliningTarget, TypeError, ErrorMessages.LOCALS_MUST_BE_MAPPING, mode, locals); |
| 808 | + } |
| 809 | + setCustomLocals(args, locals); |
| 810 | + } |
| 811 | + return args; |
865 | 812 | } |
866 | 813 |
|
867 | 814 | @Specialization |
868 | | - Object execCustomGlobalsGlobalLocals(VirtualFrame frame, Object source, PDict globals, @SuppressWarnings("unused") PNone locals, |
869 | | - @Bind("this") Node inliningTarget, |
870 | | - @Shared @Cached HashingCollectionNodes.SetItemNode setBuiltins, |
871 | | - @Shared("getCt") @Cached CodeNodes.GetCodeCallTargetNode getCt, |
872 | | - @Shared @Cached CallDispatchers.SimpleIndirectInvokeNode invoke, |
873 | | - @Shared @Cached PRaiseNode raiseNode) { |
874 | | - PCode code = createAndCheckCode(frame, inliningTarget, source, raiseNode); |
| 815 | + static Object[] customGlobals(VirtualFrame frame, Node inliningTarget, PDict globals, Object locals, TruffleString mode, |
| 816 | + @Bind PythonContext context, |
| 817 | + @Exclusive @Cached InlinedConditionProfile haveLocals, |
| 818 | + @Exclusive @Cached PyMappingCheckNode mappingCheckNode, |
| 819 | + @Exclusive @Cached GetOrCreateDictNode getOrCreateDictNode, |
| 820 | + @Exclusive @Cached HashingCollectionNodes.SetItemNode setBuiltins, |
| 821 | + @Exclusive @Cached PRaiseNode raiseNode) { |
875 | 822 | Object[] args = PArguments.create(); |
876 | | - setCustomGlobals(frame, inliningTarget, globals, setBuiltins, args); |
877 | | - setCustomLocals(args, globals); |
878 | | - RootCallTarget rootCallTarget = getCt.execute(inliningTarget, code); |
879 | | - if (rootCallTarget == null) { |
880 | | - throw raiseNode.raise(inliningTarget, ValueError, ErrorMessages.CANNOT_CREATE_CALL_TARGET, code); |
| 823 | + PythonModule builtins = context.getBuiltins(); |
| 824 | + // Builtins may be null during context initialization |
| 825 | + if (builtins != null) { |
| 826 | + PDict builtinsDict = getOrCreateDictNode.execute(inliningTarget, builtins); |
| 827 | + setBuiltins.execute(frame, inliningTarget, globals, T___BUILTINS__, builtinsDict); |
| 828 | + } |
| 829 | + PArguments.setGlobals(args, globals); |
| 830 | + if (haveLocals.profile(inliningTarget, locals instanceof PNone)) { |
| 831 | + setCustomLocals(args, globals); |
| 832 | + } else { |
| 833 | + if (!mappingCheckNode.execute(inliningTarget, locals)) { |
| 834 | + throw raiseNode.raise(inliningTarget, TypeError, ErrorMessages.LOCALS_MUST_BE_MAPPING, mode, locals); |
| 835 | + } |
| 836 | + setCustomLocals(args, locals); |
881 | 837 | } |
882 | 838 |
|
883 | | - return invoke.execute(frame, inliningTarget, rootCallTarget, args); |
884 | | - } |
885 | | - |
886 | | - @Specialization(guards = {"isMapping(inliningTarget, mappingCheckNode, locals)"}) |
887 | | - @SuppressWarnings("truffle-static-method") |
888 | | - Object execInheritGlobalsCustomLocals(VirtualFrame frame, Object source, @SuppressWarnings("unused") PNone globals, Object locals, |
889 | | - @Bind("this") Node inliningTarget, |
890 | | - @SuppressWarnings("unused") @Shared @Cached PyMappingCheckNode mappingCheckNode, |
891 | | - @Exclusive @Cached ReadCallerFrameNode readCallerFrameNode, |
892 | | - @Shared("getCt") @Cached CodeNodes.GetCodeCallTargetNode getCt, |
893 | | - @Shared @Cached CallDispatchers.SimpleIndirectInvokeNode invoke, |
894 | | - @Shared @Cached PRaiseNode raiseNode) { |
895 | | - PCode code = createAndCheckCode(frame, inliningTarget, source, raiseNode); |
896 | | - PFrame callerFrame = readCallerFrameNode.executeWith(frame, 0); |
897 | | - Object[] args = PArguments.create(); |
898 | | - inheritGlobals(callerFrame, args); |
899 | | - setCustomLocals(args, locals); |
900 | | - |
901 | | - return invoke.execute(frame, inliningTarget, getCt.execute(inliningTarget, code), args); |
| 839 | + return args; |
902 | 840 | } |
903 | 841 |
|
904 | | - @Specialization(guards = {"isMapping(inliningTarget, mappingCheckNode, locals)"}) |
905 | | - @SuppressWarnings("truffle-static-method") |
906 | | - Object execCustomGlobalsCustomLocals(VirtualFrame frame, Object source, PDict globals, Object locals, |
907 | | - @Bind("this") Node inliningTarget, |
908 | | - @SuppressWarnings("unused") @Shared @Cached PyMappingCheckNode mappingCheckNode, |
909 | | - @Shared @Cached HashingCollectionNodes.SetItemNode setBuiltins, |
910 | | - @Shared("getCt") @Cached CodeNodes.GetCodeCallTargetNode getCt, |
911 | | - @Shared @Cached CallDispatchers.SimpleIndirectInvokeNode invoke, |
912 | | - @Shared @Cached PRaiseNode raiseNode) { |
913 | | - PCode code = createAndCheckCode(frame, inliningTarget, source, raiseNode); |
914 | | - Object[] args = PArguments.create(); |
915 | | - setCustomGlobals(frame, inliningTarget, globals, setBuiltins, args); |
916 | | - setCustomLocals(args, locals); |
917 | | - |
918 | | - return invoke.execute(frame, inliningTarget, getCt.execute(inliningTarget, code), args); |
| 842 | + @Fallback |
| 843 | + static Object[] badGlobals(Node inliningTarget, Object globals, @SuppressWarnings("unused") Object locals, TruffleString mode) { |
| 844 | + throw PRaiseNode.raiseStatic(inliningTarget, TypeError, ErrorMessages.GLOBALS_MUST_BE_DICT, mode, globals); |
919 | 845 | } |
920 | 846 |
|
921 | | - @Specialization(guards = {"!isAnyNone(globals)", "!isDict(globals)"}) |
922 | | - @SuppressWarnings({"unused", "truffle-static-method"}) |
923 | | - PNone badGlobals(Object source, Object globals, Object locals, |
924 | | - @Bind("this") Node inliningTarget) { |
925 | | - throw PRaiseNode.raiseStatic(inliningTarget, TypeError, ErrorMessages.GLOBALS_MUST_BE_DICT, getMode(), globals); |
| 847 | + private static void setCustomLocals(Object[] args, Object locals) { |
| 848 | + PArguments.setSpecialArgument(args, locals); |
926 | 849 | } |
| 850 | + } |
927 | 851 |
|
928 | | - @Specialization(guards = {"isAnyNone(globals) || isDict(globals)", "!isAnyNone(locals)", "!isMapping(inliningTarget, mappingCheckNode, locals)"}) |
929 | | - @SuppressWarnings({"unused", "truffle-static-method"}) |
930 | | - PNone badLocals(Object source, PDict globals, Object locals, |
931 | | - @Bind("this") Node inliningTarget, |
932 | | - @Shared @Cached PyMappingCheckNode mappingCheckNode) { |
933 | | - throw PRaiseNode.raiseStatic(inliningTarget, TypeError, ErrorMessages.LOCALS_MUST_BE_MAPPING, getMode(), locals); |
934 | | - } |
| 852 | + @GenerateInline |
| 853 | + @GenerateCached(false) |
| 854 | + abstract static class EvalExecNode extends Node { |
| 855 | + abstract Object execute(VirtualFrame frame, Node inliningTarget, Object source, Object globals, Object locals, TruffleString mode, boolean shouldStripLeadingWhitespace); |
935 | 856 |
|
936 | | - private CompileNode getCompileNode() { |
937 | | - if (compileNode == null) { |
938 | | - CompilerDirectives.transferToInterpreterAndInvalidate(); |
939 | | - compileNode = insert(CompileNode.create(false, shouldStripLeadingWhitespace())); |
| 857 | + @Specialization |
| 858 | + static Object eval(VirtualFrame frame, Node inliningTarget, Object source, Object globals, Object locals, TruffleString mode, @SuppressWarnings("unused") boolean shouldStripLeadingWhitespace, |
| 859 | + @Cached("create(false, shouldStripLeadingWhitespace)") CompileNode compileNode, |
| 860 | + @Cached CreateEvalExecArgumentsNode createArguments, |
| 861 | + @Cached CodeNodes.GetCodeCallTargetNode getCallTarget, |
| 862 | + @Cached CallDispatchers.CallTargetCachedInvokeNode invoke, |
| 863 | + @Cached PRaiseNode raiseNode) { |
| 864 | + PCode code = compileNode.compile(frame, source, T_STRING_SOURCE, mode, -1, -1); |
| 865 | + if (code.getFreeVars().length > 0) { |
| 866 | + throw raiseNode.raise(inliningTarget, PythonBuiltinClassType.TypeError, ErrorMessages.CODE_OBJ_NO_FREE_VARIABLES, mode); |
940 | 867 | } |
941 | | - return compileNode; |
| 868 | + Object[] args = createArguments.execute(frame, inliningTarget, globals, locals, mode); |
| 869 | + RootCallTarget callTarget = getCallTarget.execute(inliningTarget, code); |
| 870 | + return invoke.execute(frame, inliningTarget, callTarget, args); |
942 | 871 | } |
| 872 | + } |
943 | 873 |
|
944 | | - private PDict getOrCreateDictNode(PythonObject object) { |
945 | | - if (getOrCreateDictNode == null) { |
946 | | - CompilerDirectives.transferToInterpreterAndInvalidate(); |
947 | | - getOrCreateDictNode = insert(GetOrCreateDictNode.create()); |
948 | | - } |
949 | | - return getOrCreateDictNode.executeCached(object); |
950 | | - } |
| 874 | + // eval(expression, globals=None, locals=None) |
| 875 | + @Builtin(name = J_EVAL, minNumOfPositionalArgs = 1, parameterNames = {"expression", "globals", "locals"}) |
| 876 | + @GenerateNodeFactory |
| 877 | + public abstract static class EvalNode extends PythonBuiltinNode { |
951 | 878 |
|
952 | | - protected boolean shouldStripLeadingWhitespace() { |
953 | | - return true; |
| 879 | + @Specialization |
| 880 | + static Object eval(VirtualFrame frame, Object source, Object globals, Object locals, |
| 881 | + @Bind Node inliningTarget, |
| 882 | + @Cached EvalExecNode evalNode) { |
| 883 | + return evalNode.execute(frame, inliningTarget, source, globals, locals, T_EVAL, true); |
954 | 884 | } |
955 | 885 | } |
956 | 886 |
|
957 | 887 | @Builtin(name = J_EXEC, minNumOfPositionalArgs = 1, parameterNames = {"source", "globals", "locals"}) |
958 | 888 | @GenerateNodeFactory |
959 | | - abstract static class ExecNode extends EvalNode { |
960 | | - protected abstract Object executeInternal(VirtualFrame frame); |
961 | | - |
962 | | - @Override |
963 | | - protected TruffleString getMode() { |
964 | | - return T_EXEC; |
965 | | - } |
966 | | - |
967 | | - @Override |
968 | | - public final Object execute(VirtualFrame frame) { |
969 | | - executeInternal(frame); |
970 | | - return PNone.NONE; |
971 | | - } |
| 889 | + public abstract static class ExecNode extends PythonBuiltinNode { |
972 | 890 |
|
973 | | - @Override |
974 | | - protected boolean shouldStripLeadingWhitespace() { |
975 | | - return false; |
| 891 | + @Specialization |
| 892 | + static Object exec(VirtualFrame frame, Object source, Object globals, Object locals, |
| 893 | + @Bind Node inliningTarget, |
| 894 | + @Cached EvalExecNode evalNode) { |
| 895 | + evalNode.execute(frame, inliningTarget, source, globals, locals, T_EXEC, false); |
| 896 | + return NONE; |
976 | 897 | } |
977 | 898 | } |
978 | 899 |
|
|
0 commit comments