@@ -85,18 +85,29 @@ protected static boolean isSameType(IsSameTypeNode isSameTypeNode, Object cls, O
85
85
return isSameTypeNode .execute (cls , cachedCls );
86
86
}
87
87
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
+ }
97
103
}
104
+ return false ;
98
105
}
99
106
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
+ */
100
111
@ ExplodeLoop (kind = LoopExplosionKind .FULL_UNROLL_UNTIL_RETURN )
101
112
protected boolean isInMro (Object cls , MroSequenceStorage mro , int sz , IsSameTypeNode isSameTypeNode ) {
102
113
PythonAbstractClass [] mroAry = mro .getInternalClassArray ();
@@ -147,19 +158,27 @@ boolean isSubtypeOfCachedMultiContext(Object derived, Object cls,
147
158
return isInMro ;
148
159
}
149
160
161
+ protected static int sub (int a , int b ) {
162
+ return a - b ;
163
+ }
164
+
150
165
@ Specialization (guards = {
151
166
"cachedCls != null" ,
152
167
"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" ,
154
171
}, replaces = "isSubtypeOfCachedMultiContext" , limit = "getVariableArgumentInlineCacheLimit()" )
155
172
boolean isVariableSubtypeOfConstantTypeCachedMultiContext (Object derived , @ SuppressWarnings ("unused" ) Object cls ,
156
173
@ SuppressWarnings ("unused" ) @ Cached ConditionProfile builtinTypeProfile ,
157
174
@ SuppressWarnings ("unused" ) @ Cached ConditionProfile builtinClassProfile ,
158
175
@ Cached IsSameTypeNode isSameTypeNode ,
159
176
@ Cached GetMroStorageNode getMro ,
177
+ @ Bind ("getMro.execute(derived).getInternalClassArray()" ) PythonAbstractClass [] mroAry ,
178
+ @ Cached ("mroAry.length" ) int derivedMroLen ,
160
179
@ 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 );
163
182
}
164
183
165
184
@ Specialization (guards = {
@@ -215,6 +234,8 @@ boolean isSubtypeOfVariableTypeCached(@SuppressWarnings("unused") Object derived
215
234
@ Specialization (guards = {
216
235
"isKindOfBuiltinClass(derived)" , // see assertion in isSubMro
217
236
"isKindOfBuiltinClass(cls)" , // see assertion in isSubMro
237
+ "mroAry.length == derivedMroLen" ,
238
+ "mroDiff < 16" ,
218
239
"isSameType(isSameClsNode, cls, cachedCls)" ,
219
240
}, limit = "getVariableArgumentInlineCacheLimit()" , replaces = {
220
241
"isSubtypeOfCachedMultiContext" ,
@@ -229,10 +250,12 @@ boolean isVariableSubtypeOfConstantTypeCached(Object derived, @SuppressWarnings(
229
250
@ Cached ("cls" ) @ SuppressWarnings ("unused" ) Object cachedCls ,
230
251
@ Cached GetMroStorageNode getMro ,
231
252
@ SuppressWarnings ("unused" ) @ Cached ("getMro.execute(cachedCls)" ) MroSequenceStorage baseMro ,
232
- @ Cached ("baseMro.getInternalClassArray().length" ) int baseMroLen ,
233
253
@ 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 ,
234
257
@ Cached @ SuppressWarnings ("unused" ) IsSameTypeNode isSameClsNode ) {
235
- return isSubMro (cachedCls , getMro . execute ( derived ), baseMroLen , isSameTypeInLoopNode );
258
+ return isSubMro (cachedCls , mroAry , mroDiff , isSameTypeInLoopNode );
236
259
}
237
260
238
261
@ Specialization (guards = {
0 commit comments