@@ -85,18 +85,29 @@ protected static boolean isSameType(IsSameTypeNode isSameTypeNode, Object cls, O
8585 return isSameTypeNode .execute (cls , cachedCls );
8686 }
8787
88- protected boolean isSubMro (Object base , MroSequenceStorage derivedMro , int baseMroLen , IsSameTypeNode isSameTypeNode ) {
89- CompilerAsserts .partialEvaluationConstant (baseMroLen );
90- PythonAbstractClass [] derivedMroAry = derivedMro .getInternalClassArray ();
91- int derivedMroLen = derivedMroAry .length ;
92- int offset = derivedMroLen - baseMroLen ;
93- if (offset >= 0 ) {
94- return isSameType (isSameTypeNode , derivedMroAry [offset ], base );
95- } else {
96- return false ;
88+ /**
89+ * This method is used to search for a constant base type in the mro of
90+ * non-constant potential subtypes when all subtypes' MROs have the same
91+ * length. Since the entire base mro must strictly be behind the base, we
92+ * only need to search from the beginning of the mro to the length
93+ * difference.
94+ */
95+ @ ExplodeLoop (kind = LoopExplosionKind .FULL_UNROLL_UNTIL_RETURN )
96+ protected boolean isSubMro (Object base , PythonAbstractClass [] derivedMroAry , int mroDiff , IsSameTypeNode isSameTypeNode ) {
97+ CompilerAsserts .partialEvaluationConstant (base );
98+ CompilerAsserts .partialEvaluationConstant (mroDiff );
99+ for (int i = 0 ; i <= mroDiff ; i ++) {
100+ if (isSameType (isSameTypeNode , derivedMroAry [i ], base )) {
101+ return true ;
102+ }
97103 }
104+ return false ;
98105 }
99106
107+ /**
108+ * This method is used to search in a constant length subtype mro for a
109+ * (non-constant) base type. It has to loop over the entire mro to do this.
110+ */
100111 @ ExplodeLoop (kind = LoopExplosionKind .FULL_UNROLL_UNTIL_RETURN )
101112 protected boolean isInMro (Object cls , MroSequenceStorage mro , int sz , IsSameTypeNode isSameTypeNode ) {
102113 PythonAbstractClass [] mroAry = mro .getInternalClassArray ();
@@ -147,19 +158,27 @@ boolean isSubtypeOfCachedMultiContext(Object derived, Object cls,
147158 return isInMro ;
148159 }
149160
161+ protected static int sub (int a , int b ) {
162+ return a - b ;
163+ }
164+
150165 @ Specialization (guards = {
151166 "cachedCls != null" ,
152167 "getType(cls, builtinTypeProfile, builtinClassProfile) == cachedCls" ,
153- "isKindOfBuiltinClass(derived)" // see assertion in isSubMro
168+ "isKindOfBuiltinClass(derived)" , // see assertion in isSubMro
169+ "mroAry.length == derivedMroLen" ,
170+ "mroDiff < 16" ,
154171 }, replaces = "isSubtypeOfCachedMultiContext" , limit = "getVariableArgumentInlineCacheLimit()" )
155172 boolean isVariableSubtypeOfConstantTypeCachedMultiContext (Object derived , @ SuppressWarnings ("unused" ) Object cls ,
156173 @ SuppressWarnings ("unused" ) @ Cached ConditionProfile builtinTypeProfile ,
157174 @ SuppressWarnings ("unused" ) @ Cached ConditionProfile builtinClassProfile ,
158175 @ Cached IsSameTypeNode isSameTypeNode ,
159176 @ Cached GetMroStorageNode getMro ,
177+ @ Bind ("getMro.execute(derived).getInternalClassArray()" ) PythonAbstractClass [] mroAry ,
178+ @ Cached ("mroAry.length" ) int derivedMroLen ,
160179 @ Cached ("getType(cls, builtinTypeProfile, builtinClassProfile)" ) PythonBuiltinClassType cachedCls ,
161- @ Cached ("getMro.execute(cachedCls).getInternalClassArray().length" ) int baseMroLen ) {
162- return isSubMro (cachedCls , getMro . execute ( derived ), baseMroLen , isSameTypeNode );
180+ @ Cached ("sub(derivedMroLen, getMro.execute(cachedCls).getInternalClassArray().length) " ) int mroDiff ) {
181+ return isSubMro (cachedCls , mroAry , mroDiff , isSameTypeNode );
163182 }
164183
165184 @ Specialization (guards = {
@@ -215,6 +234,8 @@ boolean isSubtypeOfVariableTypeCached(@SuppressWarnings("unused") Object derived
215234 @ Specialization (guards = {
216235 "isKindOfBuiltinClass(derived)" , // see assertion in isSubMro
217236 "isKindOfBuiltinClass(cls)" , // see assertion in isSubMro
237+ "mroAry.length == derivedMroLen" ,
238+ "mroDiff < 16" ,
218239 "isSameType(isSameClsNode, cls, cachedCls)" ,
219240 }, limit = "getVariableArgumentInlineCacheLimit()" , replaces = {
220241 "isSubtypeOfCachedMultiContext" ,
@@ -229,10 +250,12 @@ boolean isVariableSubtypeOfConstantTypeCached(Object derived, @SuppressWarnings(
229250 @ Cached ("cls" ) @ SuppressWarnings ("unused" ) Object cachedCls ,
230251 @ Cached GetMroStorageNode getMro ,
231252 @ SuppressWarnings ("unused" ) @ Cached ("getMro.execute(cachedCls)" ) MroSequenceStorage baseMro ,
232- @ Cached ("baseMro.getInternalClassArray().length" ) int baseMroLen ,
233253 @ Cached IsSameTypeNode isSameTypeInLoopNode ,
254+ @ Bind ("getMro.execute(derived).getInternalClassArray()" ) PythonAbstractClass [] mroAry ,
255+ @ Cached ("mroAry.length" ) int derivedMroLen ,
256+ @ Cached ("sub(derivedMroLen, baseMro.getInternalClassArray().length)" ) int mroDiff ,
234257 @ Cached @ SuppressWarnings ("unused" ) IsSameTypeNode isSameClsNode ) {
235- return isSubMro (cachedCls , getMro . execute ( derived ), baseMroLen , isSameTypeInLoopNode );
258+ return isSubMro (cachedCls , mroAry , mroDiff , isSameTypeInLoopNode );
236259 }
237260
238261 @ Specialization (guards = {
0 commit comments