61
61
@ ImportStatic (PythonOptions .class )
62
62
@ NodeInfo (shortName = "cpython://Objects/abstract.c/abstract_issubclass" )
63
63
public abstract class AbstractObjectIsSubclassNode extends PNodeWithContext {
64
+ static final int MAX_RECURSION = 3 ; // Cannot use PythonOptions on fast-path
65
+
64
66
public static AbstractObjectIsSubclassNode create () {
65
67
return AbstractObjectIsSubclassNodeGen .create ();
66
68
}
67
69
68
- protected abstract boolean executeInternal (Frame frame , Object derived , Object cls );
70
+ protected abstract boolean executeInternal (Frame frame , Object derived , Object cls , int depth );
69
71
70
72
public final boolean execute (VirtualFrame frame , Object derived , Object cls ) {
71
- return executeInternal (frame , derived , cls );
73
+ return executeInternal (frame , derived , cls , 0 );
72
74
}
73
75
74
76
public final boolean execute (Object derived , Object cls ) {
@@ -77,7 +79,7 @@ public final boolean execute(Object derived, Object cls) {
77
79
78
80
@ Specialization (guards = "isSameMetaObject(isSameTypeNode, derived, cls)" , limit = "1" )
79
81
@ SuppressWarnings ("unused" )
80
- static boolean doSameClass (Object derived , Object cls ,
82
+ static boolean doSameClass (Object derived , Object cls , @ SuppressWarnings ( "unused" ) int depth ,
81
83
@ Shared ("isSameType" ) @ Cached IsSameTypeNode isSameTypeNode ) {
82
84
return true ;
83
85
}
@@ -88,8 +90,8 @@ protected static int[] observedSize() {
88
90
return ary ;
89
91
}
90
92
91
- @ Specialization (guards = {"!isSameMetaObject(isSameTypeNode, derived, cls)" , "derived == cachedDerived" , "cls == cachedCls" }, limit = "getCallSiteInlineCacheMaxDepth()" )
92
- static boolean doSubclass (VirtualFrame frame , @ SuppressWarnings ("unused" ) Object derived , @ SuppressWarnings ("unused" ) Object cls ,
93
+ @ Specialization (guards = {"depth < MAX_RECURSION" , " !isSameMetaObject(isSameTypeNode, derived, cls)" , "derived == cachedDerived" , "cls == cachedCls" }, limit = "getCallSiteInlineCacheMaxDepth()" )
94
+ static boolean doSubclass (VirtualFrame frame , @ SuppressWarnings ("unused" ) Object derived , @ SuppressWarnings ("unused" ) Object cls , int depth ,
93
95
@ Cached (value = "observedSize()" , dimensions = 1 ) int [] observedSizeArray ,
94
96
@ Cached ("derived" ) Object cachedDerived ,
95
97
@ Cached ("cls" ) Object cachedCls ,
@@ -108,41 +110,41 @@ static boolean doSubclass(VirtualFrame frame, @SuppressWarnings("unused") Object
108
110
CompilerDirectives .transferToInterpreterAndInvalidate ();
109
111
observedSizeArray [0 ] = basesAry .length ;
110
112
}
111
- if (observedSizeArray [0 ] > 0 && observedSizeArray [0 ] < 32 && observedSizeArray [0 ] == basesAry .length ) {
113
+ if (observedSizeArray [0 ] > 0 && observedSizeArray [0 ] < ( 32 / depth ) && observedSizeArray [0 ] == basesAry .length ) {
112
114
// we observe a short constant size
113
- return loopBases (frame , cachedCls , basesAry , isSubclassNode );
115
+ return loopBases (frame , cachedCls , basesAry , isSubclassNode , depth );
114
116
} else if (observedSizeArray [0 ] > 0 ) {
115
117
// the observed size is too large or not constant, disable explosion
116
118
CompilerDirectives .transferToInterpreterAndInvalidate ();
117
119
observedSizeArray [0 ] = -1 ;
118
120
}
119
- return loopUnexploded (frame , cachedCls , isSubclassNode , basesAry );
121
+ return loopUnexploded (frame , cachedCls , isSubclassNode , basesAry , depth );
120
122
}
121
123
122
- private static boolean loopUnexploded (VirtualFrame frame , Object cachedCls , AbstractObjectIsSubclassNode isSubclassNode , Object [] basesAry ) {
124
+ private static boolean loopUnexploded (VirtualFrame frame , Object cachedCls , AbstractObjectIsSubclassNode isSubclassNode , Object [] basesAry , int depth ) {
123
125
for (Object baseCls : basesAry ) {
124
- if (isSubclassNode .execute (frame , baseCls , cachedCls )) {
126
+ if (isSubclassNode .executeInternal (frame , baseCls , cachedCls , depth + 1 )) {
125
127
return true ;
126
128
}
127
129
}
128
130
return false ;
129
131
}
130
132
131
133
@ ExplodeLoop
132
- private static boolean loopBases (VirtualFrame frame , Object cachedCls , Object [] bases , AbstractObjectIsSubclassNode isSubclassNode ) {
134
+ private static boolean loopBases (VirtualFrame frame , Object cachedCls , Object [] bases , AbstractObjectIsSubclassNode isSubclassNode , int depth ) {
133
135
for (int i = 0 ; i < bases .length ; i ++) {
134
- if (isSubclassNode .execute (frame , bases [i ], cachedCls )) {
136
+ if (isSubclassNode .executeInternal (frame , bases [i ], cachedCls , depth + 1 )) {
135
137
return true ;
136
138
}
137
139
}
138
140
return false ;
139
141
}
140
142
141
143
@ Specialization (replaces = {"doSubclass" , "doSameClass" })
142
- static boolean doGeneric (VirtualFrame frame , Object derived , Object cls ,
144
+ static boolean doGeneric (VirtualFrame frame , Object derived , Object cls , int depth ,
143
145
@ Cached SequenceStorageNodes .LenNode lenNode ,
144
146
@ Cached AbstractObjectGetBasesNode getBasesNode ,
145
- @ Cached AbstractObjectIsSubclassNode isSubclassNode ,
147
+ @ Cached ( "createRecursive(depth)" ) AbstractObjectIsSubclassNode isSubclassNode ,
146
148
@ Shared ("isSameType" ) @ Cached IsSameTypeNode isSameTypeNode ,
147
149
@ Cached GetObjectArrayNode getObjectArrayNode ) {
148
150
if (isSameMetaObject (isSameTypeNode , derived , cls )) {
@@ -155,13 +157,20 @@ static boolean doGeneric(VirtualFrame frame, Object derived, Object cls,
155
157
}
156
158
157
159
for (Object baseCls : getObjectArrayNode .execute (bases )) {
158
- if (isSubclassNode .execute (frame , baseCls , cls )) {
160
+ if (isSubclassNode .executeInternal (frame , baseCls , cls , depth + 1 )) {
159
161
return true ;
160
162
}
161
163
}
162
164
return false ;
163
165
}
164
166
167
+ protected AbstractObjectIsSubclassNode createRecursive (int depth ) {
168
+ if (depth >= MAX_RECURSION ) {
169
+ return AbstractObjectIsSubclassNodeGen .getUncached ();
170
+ }
171
+ return AbstractObjectIsSubclassNodeGen .create ();
172
+ }
173
+
165
174
private static boolean isEmpty (PTuple bases , SequenceStorageNodes .LenNode lenNode ) {
166
175
return lenNode .execute (bases .getSequenceStorage ()) == 0 ;
167
176
}
0 commit comments