|
70 | 70 | import com.oracle.graal.python.builtins.objects.common.SequenceNodesFactory.GetObjectArrayNodeGen;
|
71 | 71 | import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.GetInternalObjectArrayNode;
|
72 | 72 | import com.oracle.graal.python.builtins.objects.dict.PDict;
|
| 73 | +import com.oracle.graal.python.builtins.objects.function.PFunction; |
73 | 74 | import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
|
74 | 75 | import com.oracle.graal.python.builtins.objects.tuple.PTuple;
|
75 | 76 | import com.oracle.graal.python.builtins.objects.type.PythonManagedClass.FlagsContainer;
|
|
90 | 91 | import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DICT__;
|
91 | 92 | import static com.oracle.graal.python.nodes.SpecialAttributeNames.__SLOTS__;
|
92 | 93 | import com.oracle.graal.python.nodes.SpecialMethodNames;
|
| 94 | +import static com.oracle.graal.python.nodes.SpecialMethodNames.MRO; |
93 | 95 | import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETATTRIBUTE__;
|
94 | 96 | import static com.oracle.graal.python.nodes.SpecialMethodNames.__NEW__;
|
95 | 97 | import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode;
|
| 98 | +import com.oracle.graal.python.nodes.call.special.CallUnaryMethodNode; |
96 | 99 | import com.oracle.graal.python.nodes.call.special.LookupAndCallBinaryNode;
|
97 | 100 | import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
|
98 | 101 | import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
|
99 | 102 | import com.oracle.graal.python.nodes.truffle.PythonTypes;
|
100 | 103 | import com.oracle.graal.python.runtime.PythonContext;
|
101 | 104 | import com.oracle.graal.python.runtime.exception.PException;
|
| 105 | +import com.oracle.graal.python.runtime.sequence.PSequence; |
102 | 106 | import com.oracle.graal.python.runtime.sequence.storage.MroSequenceStorage;
|
103 | 107 | import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
|
104 | 108 | import com.oracle.graal.python.util.PythonUtils;
|
@@ -232,7 +236,11 @@ public abstract static class GetMroStorageNode extends PNodeWithContext {
|
232 | 236 | public abstract MroSequenceStorage execute(Object obj);
|
233 | 237 |
|
234 | 238 | @Specialization
|
235 |
| - static MroSequenceStorage doPythonClass(PythonManagedClass obj) { |
| 239 | + static MroSequenceStorage doPythonClass(PythonManagedClass obj, |
| 240 | + @Cached("createBinaryProfile()") ConditionProfile notInitialized) { |
| 241 | + if (!notInitialized.profile(obj.getMethodResolutionOrder().isInitialized())) { |
| 242 | + obj.getMethodResolutionOrder().setInternalArrayObject(TypeNodes.ComputeMroNode.doSlowPath(obj, false)); |
| 243 | + } |
236 | 244 | return obj.getMethodResolutionOrder();
|
237 | 245 | }
|
238 | 246 |
|
@@ -277,7 +285,7 @@ static MroSequenceStorage doNativeClass(PythonNativeClass obj,
|
277 | 285 | @TruffleBoundary
|
278 | 286 | static MroSequenceStorage doSlowPath(Object obj) {
|
279 | 287 | if (obj instanceof PythonManagedClass) {
|
280 |
| - return ((PythonManagedClass) obj).getMethodResolutionOrder(); |
| 288 | + return doPythonClass((PythonManagedClass) obj, ConditionProfile.getUncached()); |
281 | 289 | } else if (obj instanceof PythonBuiltinClassType) {
|
282 | 290 | return PythonLanguage.getCore().lookupType((PythonBuiltinClassType) obj).getMethodResolutionOrder();
|
283 | 291 | } else if (PGuards.isNativeClass(obj)) {
|
@@ -1085,14 +1093,29 @@ public abstract static class ComputeMroNode extends Node {
|
1085 | 1093 |
|
1086 | 1094 | @TruffleBoundary
|
1087 | 1095 | public static PythonAbstractClass[] doSlowPath(PythonAbstractClass cls) {
|
1088 |
| - return computeMethodResolutionOrder(cls); |
| 1096 | + return doSlowPath(cls, true); |
1089 | 1097 | }
|
1090 | 1098 |
|
1091 |
| - private static PythonAbstractClass[] computeMethodResolutionOrder(PythonAbstractClass cls) { |
| 1099 | + @TruffleBoundary |
| 1100 | + public static PythonAbstractClass[] doSlowPath(PythonAbstractClass cls, boolean invokeMro) { |
| 1101 | + return computeMethodResolutionOrder(cls, invokeMro); |
| 1102 | + } |
| 1103 | + |
| 1104 | + private static PythonAbstractClass[] computeMethodResolutionOrder(PythonAbstractClass cls, boolean invokeMro) { |
1092 | 1105 | CompilerAsserts.neverPartOfCompilation();
|
1093 | 1106 |
|
1094 | 1107 | PythonAbstractClass[] currentMRO = null;
|
1095 | 1108 |
|
| 1109 | + Object type = PythonObjectLibrary.getUncached().getLazyPythonClass(cls); |
| 1110 | + if (invokeMro) { |
| 1111 | + if (type instanceof LazyPythonClass) { |
| 1112 | + PythonAbstractClass[] typeMRO = getMRO((LazyPythonClass) type, cls); |
| 1113 | + if (typeMRO != null) { |
| 1114 | + return typeMRO; |
| 1115 | + } |
| 1116 | + } |
| 1117 | + } |
| 1118 | + |
1096 | 1119 | PythonAbstractClass[] baseClasses = GetBaseClassesNodeGen.getUncached().execute(cls);
|
1097 | 1120 | if (baseClasses.length == 0) {
|
1098 | 1121 | currentMRO = new PythonAbstractClass[]{cls};
|
@@ -1121,6 +1144,40 @@ private static PythonAbstractClass[] computeMethodResolutionOrder(PythonAbstract
|
1121 | 1144 | return currentMRO;
|
1122 | 1145 | }
|
1123 | 1146 |
|
| 1147 | + private static PythonAbstractClass[] getMRO(LazyPythonClass type, PythonAbstractClass cls) { |
| 1148 | + if (type instanceof PythonClass) { |
| 1149 | + Object mroMeth = LookupAttributeInMRONode.Dynamic.getUncached().execute(type, MRO); |
| 1150 | + if (mroMeth instanceof PFunction) { |
| 1151 | + Object mroObj = CallUnaryMethodNode.getUncached().executeObject(mroMeth, cls); |
| 1152 | + if (mroObj instanceof PSequence) { |
| 1153 | + return mroCheck(cls, ((PSequence) mroObj).getSequenceStorage().getInternalArray()); |
| 1154 | + } |
| 1155 | + throw PRaiseNode.getUncached().raise(TypeError, ErrorMessages.OBJ_NOT_ITERABLE, cls); |
| 1156 | + } |
| 1157 | + } |
| 1158 | + return null; |
| 1159 | + } |
| 1160 | + |
| 1161 | + private static PythonAbstractClass[] mroCheck(LazyPythonClass cls, Object[] mro) { |
| 1162 | + List<PythonAbstractClass> resultMro = new ArrayList<>(mro.length); |
| 1163 | + for (int i = 0; i < mro.length; i++) { |
| 1164 | + Object object = mro[i]; |
| 1165 | + if (object == null) { |
| 1166 | + continue; |
| 1167 | + } |
| 1168 | + if (!PythonObjectLibrary.getUncached().isLazyPythonClass(object)) { |
| 1169 | + throw PRaiseNode.getUncached().raise(TypeError, ErrorMessages.S_RETURNED_NON_CLASS, "mro()", object); |
| 1170 | + } |
| 1171 | + if (!IsSubtypeNode.getUncached().execute(cls, object)) { |
| 1172 | + // XXX typeobject.c/mro_check() does !PyType_IsSubtype(solid, solid_base(base)) |
| 1173 | + // could reuse GetBestBaseClassNode.solidBase(), but need frame for that |
| 1174 | + throw PRaiseNode.getUncached().raise(TypeError, ErrorMessages.S_RETURNED_BASE_WITH_UNSUITABLE_LAYOUT, "mro()", object); |
| 1175 | + } |
| 1176 | + resultMro.add((PythonAbstractClass) object); |
| 1177 | + } |
| 1178 | + return resultMro.toArray(new PythonAbstractClass[resultMro.size()]); |
| 1179 | + } |
| 1180 | + |
1124 | 1181 | private static PythonAbstractClass[] mergeMROs(MROMergeState[] toMerge, List<PythonAbstractClass> mro) {
|
1125 | 1182 | int idx;
|
1126 | 1183 | scan: for (idx = 0; idx < toMerge.length; idx++) {
|
|
0 commit comments