|
118 | 118 | import com.oracle.graal.python.nodes.PGuards;
|
119 | 119 | import com.oracle.graal.python.nodes.PNodeWithContext;
|
120 | 120 | import com.oracle.graal.python.nodes.PNodeWithState;
|
| 121 | +import com.oracle.graal.python.nodes.PRaiseNode; |
121 | 122 | import com.oracle.graal.python.nodes.SpecialAttributeNames;
|
122 | 123 | import com.oracle.graal.python.nodes.StringLiterals;
|
123 | 124 | import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode;
|
124 | 125 | import com.oracle.graal.python.nodes.attributes.LookupCallableSlotInMRONode;
|
125 | 126 | import com.oracle.graal.python.nodes.attributes.ReadAttributeFromDynamicObjectNode;
|
126 | 127 | import com.oracle.graal.python.nodes.attributes.WriteAttributeToDynamicObjectNode;
|
| 128 | +import com.oracle.graal.python.nodes.attributes.WriteAttributeToObjectNode; |
127 | 129 | import com.oracle.graal.python.nodes.call.CallNode;
|
128 | 130 | import com.oracle.graal.python.nodes.call.special.CallTernaryMethodNode;
|
129 | 131 | import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
|
|
147 | 149 | import com.oracle.truffle.api.dsl.Cached;
|
148 | 150 | import com.oracle.truffle.api.dsl.Cached.Shared;
|
149 | 151 | import com.oracle.truffle.api.dsl.Fallback;
|
| 152 | +import com.oracle.truffle.api.dsl.GenerateCached; |
| 153 | +import com.oracle.truffle.api.dsl.GenerateInline; |
150 | 154 | import com.oracle.truffle.api.dsl.GenerateUncached;
|
151 | 155 | import com.oracle.truffle.api.dsl.ImportStatic;
|
152 | 156 | import com.oracle.truffle.api.dsl.NeverDefault;
|
@@ -920,6 +924,85 @@ public static DefaultObjectReprNode create() {
|
920 | 924 | }
|
921 | 925 | }
|
922 | 926 |
|
| 927 | + @GenerateInline |
| 928 | + @GenerateCached(false) |
| 929 | + @GenerateUncached |
| 930 | + public abstract static class GenericSetAttrNode extends Node { |
| 931 | + public abstract void execute(Node inliningTarget, VirtualFrame frame, Object object, Object key, Object value, WriteAttributeToObjectNode writeNode); |
| 932 | + |
| 933 | + @Specialization |
| 934 | + static void doStringKey(Node inliningTarget, VirtualFrame frame, Object object, TruffleString key, Object value, WriteAttributeToObjectNode writeNode, |
| 935 | + @Shared @Cached InlinedGetClassNode getClassNode, |
| 936 | + @Shared @Cached CallSetHelper callSetHelper, |
| 937 | + @Shared @Cached LookupAttributeInMRONode.Dynamic getExisting, |
| 938 | + @Shared @Cached PRaiseNode raiseNode) { |
| 939 | + Object type = getClassNode.execute(inliningTarget, object); |
| 940 | + Object descr = getExisting.execute(type, key); |
| 941 | + boolean calledSet = callSetHelper.execute(inliningTarget, frame, descr, object, value); |
| 942 | + if (calledSet) { |
| 943 | + return; |
| 944 | + } |
| 945 | + boolean wroteAttr = writeNode.execute(object, key, value); |
| 946 | + if (wroteAttr) { |
| 947 | + return; |
| 948 | + } |
| 949 | + if (descr != PNone.NO_VALUE) { |
| 950 | + throw raiseNode.raise(AttributeError, ErrorMessages.ATTR_S_READONLY, key); |
| 951 | + } else { |
| 952 | + throw raiseNode.raise(AttributeError, ErrorMessages.HAS_NO_ATTR, object, key); |
| 953 | + } |
| 954 | + } |
| 955 | + |
| 956 | + @Specialization(replaces = "doStringKey") |
| 957 | + static void doIt(Node inliningTarget, VirtualFrame frame, Object object, Object keyObject, Object value, WriteAttributeToObjectNode writeNode, |
| 958 | + @Shared @Cached InlinedGetClassNode getClassNode, |
| 959 | + @Shared @Cached CallSetHelper callSetHelper, |
| 960 | + @Shared @Cached LookupAttributeInMRONode.Dynamic getExisting, |
| 961 | + @Shared @Cached PRaiseNode raiseNode, |
| 962 | + @Cached CastToTruffleStringNode castKeyToStringNode) { |
| 963 | + TruffleString key; |
| 964 | + try { |
| 965 | + key = castKeyToStringNode.execute(keyObject); |
| 966 | + } catch (CannotCastException e) { |
| 967 | + throw raiseNode.raise(PythonBuiltinClassType.TypeError, ATTR_NAME_MUST_BE_STRING, keyObject); |
| 968 | + } |
| 969 | + doStringKey(inliningTarget, frame, object, key, value, writeNode, getClassNode, callSetHelper, getExisting, raiseNode); |
| 970 | + } |
| 971 | + |
| 972 | + public static GenericSetAttrNode getUncached() { |
| 973 | + return ObjectNodesFactory.GenericSetAttrNodeGen.getUncached(); |
| 974 | + } |
| 975 | + |
| 976 | + @GenerateInline |
| 977 | + @GenerateCached(false) |
| 978 | + @GenerateUncached |
| 979 | + @ImportStatic({SpecialMethodSlot.class, PGuards.class}) |
| 980 | + abstract static class CallSetHelper extends Node { |
| 981 | + abstract boolean execute(Node inliningTarget, VirtualFrame frame, Object descr, Object object, Object value); |
| 982 | + |
| 983 | + @Specialization(guards = "isNoValue(descr)") |
| 984 | + @SuppressWarnings("unused") |
| 985 | + static boolean call(Node inliningTarget, VirtualFrame frame, Object descr, Object object, Object value) { |
| 986 | + return false; |
| 987 | + } |
| 988 | + |
| 989 | + @Specialization(guards = "!isNoValue(descr)") |
| 990 | + static boolean call(Node inliningTarget, VirtualFrame frame, Object descr, Object object, Object value, |
| 991 | + @Cached InlinedGetClassNode getClassNode, |
| 992 | + @Cached(parameters = "Set") LookupCallableSlotInMRONode lookup, |
| 993 | + @Cached CallTernaryMethodNode call) { |
| 994 | + Object descrClass = getClassNode.execute(inliningTarget, descr); |
| 995 | + Object setMethod = lookup.execute(descrClass); |
| 996 | + if (setMethod == PNone.NO_VALUE) { |
| 997 | + return false; |
| 998 | + } else { |
| 999 | + call.execute(frame, setMethod, descr, object, value); |
| 1000 | + return true; |
| 1001 | + } |
| 1002 | + } |
| 1003 | + } |
| 1004 | + } |
| 1005 | + |
923 | 1006 | public abstract static class AbstractSetattrNode extends PythonTernaryBuiltinNode {
|
924 | 1007 | @Child GetClassNode getDescClassNode;
|
925 | 1008 | @Child LookupCallableSlotInMRONode lookupSetNode;
|
|
0 commit comments