Skip to content

Commit 64c88b9

Browse files
committed
Refactor issubclass and isinstance checks
1 parent c5c7729 commit 64c88b9

23 files changed

+189
-236
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ArrayModuleBuiltins.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ private static Object doReconstruct(VirtualFrame frame, Node inliningTarget, Obj
137137
ArrayBuiltins.FromBytesNode fromBytesNode, ArrayBuiltins.FromUnicodeNode fromUnicodeNode, IsSubtypeNode isSubtypeNode,
138138
ArrayBuiltins.ByteSwapNode byteSwapNode, BufferFormat format,
139139
TypeNodes.GetInstanceShape getInstanceShape, PRaiseNode raiseNode) {
140-
if (!isSubtypeNode.execute(frame, arrayType, PythonBuiltinClassType.PArray)) {
140+
if (!isSubtypeNode.execute(arrayType, PythonBuiltinClassType.PArray)) {
141141
throw raiseNode.raise(inliningTarget, TypeError, ErrorMessages.N_NOT_SUBTYPE_OF_ARRAY, arrayType);
142142
}
143143
MachineFormat machineFormat = MachineFormat.fromCode(mformatCode);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java

Lines changed: 41 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,7 @@
163163
import com.oracle.graal.python.builtins.objects.type.SpecialMethodSlot;
164164
import com.oracle.graal.python.builtins.objects.type.TpSlots;
165165
import com.oracle.graal.python.builtins.objects.type.TpSlots.GetObjectSlotsNode;
166-
import com.oracle.graal.python.builtins.objects.type.TypeBuiltins;
167-
import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsSameTypeNode;
166+
import com.oracle.graal.python.builtins.objects.type.TypeNodes;
168167
import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsTypeNode;
169168
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotIterNext.CallSlotTpIterNextNode;
170169
import com.oracle.graal.python.builtins.objects.type.slots.TpSlotUnaryFunc.CallSlotUnaryNode;
@@ -237,6 +236,7 @@
237236
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryClinicBuiltinNode;
238237
import com.oracle.graal.python.nodes.function.builtins.PythonVarargsBuiltinNode;
239238
import com.oracle.graal.python.nodes.function.builtins.clinic.ArgumentClinicProvider;
239+
import com.oracle.graal.python.nodes.object.BuiltinClassProfiles.IsBuiltinClassExactProfile;
240240
import com.oracle.graal.python.nodes.object.BuiltinClassProfiles.IsBuiltinObjectProfile;
241241
import com.oracle.graal.python.nodes.object.GetClassNode;
242242
import com.oracle.graal.python.nodes.object.GetOrCreateDictNode;
@@ -308,7 +308,6 @@
308308
import com.oracle.truffle.api.strings.TruffleString;
309309
import com.oracle.truffle.api.strings.TruffleString.Encoding;
310310
import com.oracle.truffle.api.strings.TruffleStringBuilder;
311-
import com.oracle.truffle.api.utilities.TriState;
312311

313312
@CoreFunctions(defineModule = J_BUILTINS, isEager = true)
314313
public final class BuiltinFunctions extends PythonBuiltins {
@@ -1381,40 +1380,33 @@ public IsInstanceNode createRecursive(byte newDepth) {
13811380
return BuiltinFunctionsFactory.IsInstanceNodeFactory.create(newDepth);
13821381
}
13831382

1384-
private static TriState isInstanceCheckInternal(VirtualFrame frame, Object instance, Object cls, LookupAndCallBinaryNode instanceCheckNode,
1385-
PyObjectIsTrueNode castToBooleanNode) {
1383+
@Specialization(guards = "!isPTuple(cls)")
1384+
static boolean isInstance(VirtualFrame frame, Object instance, Object cls,
1385+
@Bind Node inliningTarget,
1386+
@Cached GetClassNode getClsClassNode,
1387+
@Cached IsBuiltinClassExactProfile classProfile,
1388+
@Cached GetClassNode getInstanceClassNode,
1389+
@Cached TypeNodes.IsSameTypeNode isSameTypeNode,
1390+
@Cached("create(InstanceCheck)") LookupAndCallBinaryNode instanceCheckNode,
1391+
@Cached PyObjectIsTrueNode isTrueNode,
1392+
@Cached TypeNodes.GenericInstanceCheckNode genericInstanceCheckNode,
1393+
@Cached InlinedBranchProfile noInstanceCheckProfile) {
1394+
if (isSameTypeNode.execute(inliningTarget, getInstanceClassNode.execute(inliningTarget, instance), cls)) {
1395+
// Exact match, don't call __instancecheck__
1396+
return true;
1397+
}
1398+
if (classProfile.profileClass(inliningTarget, getClsClassNode.execute(inliningTarget, cls), PythonBuiltinClassType.PythonClass)) {
1399+
// Avoid the lookup and call overhead when we know we're calling
1400+
// type.__instancecheck__
1401+
return genericInstanceCheckNode.execute(frame, inliningTarget, instance, cls);
1402+
}
13861403
try {
1387-
Object instanceCheckResult = instanceCheckNode.executeObject(frame, cls, instance);
1388-
return TriState.valueOf(castToBooleanNode.execute(frame, instanceCheckResult));
1404+
Object result = instanceCheckNode.executeObject(frame, cls, instance);
1405+
return isTrueNode.execute(frame, result);
13891406
} catch (SpecialMethodNotFound ignore) {
1390-
return TriState.UNDEFINED;
1391-
}
1392-
}
1393-
1394-
@Specialization(guards = "isPythonClass(cls)")
1395-
static boolean isInstance(VirtualFrame frame, Object instance, Object cls,
1396-
@Bind("this") Node inliningTarget,
1397-
@Shared("instanceCheck") @Cached("create(InstanceCheck)") LookupAndCallBinaryNode instanceCheckNode,
1398-
@Exclusive @Cached PyObjectIsTrueNode castToBooleanNode,
1399-
@Cached GetClassNode getClassNode,
1400-
@Cached IsSameTypeNode isSameTypeNode,
1401-
@Cached IsSubtypeNode isSubtypeNode) {
1402-
Object instanceClass = getClassNode.execute(inliningTarget, instance);
1403-
return isSameTypeNode.execute(inliningTarget, instanceClass, cls) || isSubtypeNode.execute(frame, instanceClass, cls)//
1404-
|| isInstanceCheckInternal(frame, instance, cls, instanceCheckNode, castToBooleanNode) == TriState.TRUE;
1405-
}
1406-
1407-
@Specialization(guards = {"!isPTuple(cls)", "!isPythonClass(cls)"})
1408-
static boolean isInstance(VirtualFrame frame, Object instance, Object cls,
1409-
@Bind("this") Node inliningTarget,
1410-
@Shared("instanceCheck") @Cached("create(InstanceCheck)") LookupAndCallBinaryNode instanceCheckNode,
1411-
@Exclusive @Cached PyObjectIsTrueNode castToBooleanNode,
1412-
@Cached TypeBuiltins.InstanceCheckNode typeInstanceCheckNode) {
1413-
TriState check = isInstanceCheckInternal(frame, instance, cls, instanceCheckNode, castToBooleanNode);
1414-
if (check == TriState.UNDEFINED) {
1415-
return typeInstanceCheckNode.executeWith(frame, cls, instance);
1407+
noInstanceCheckProfile.enter(inliningTarget);
1408+
return genericInstanceCheckNode.execute(frame, inliningTarget, instance, cls);
14161409
}
1417-
return check == TriState.TRUE;
14181410
}
14191411
}
14201412

@@ -1439,14 +1431,24 @@ public IsSubClassNode createRecursive(byte newDepth) {
14391431

14401432
@Specialization(guards = "!isPTuple(cls)")
14411433
static boolean isSubclass(VirtualFrame frame, Object derived, Object cls,
1434+
@Bind Node inliningTarget,
1435+
@Cached GetClassNode getClsClassNode,
1436+
@Cached IsBuiltinClassExactProfile classProfile,
14421437
@Cached("create(Subclasscheck)") LookupAndCallBinaryNode subclassCheckNode,
1443-
@Cached PyObjectIsTrueNode castToBooleanNode,
1444-
@Cached IsSubtypeNode isSubtypeNode) {
1438+
@Cached PyObjectIsTrueNode isTrueNode,
1439+
@Cached TypeNodes.GenericSubclassCheckNode genericSubclassCheckNode,
1440+
@Cached InlinedBranchProfile noInstanceCheckProfile) {
1441+
if (classProfile.profileClass(inliningTarget, getClsClassNode.execute(inliningTarget, cls), PythonBuiltinClassType.PythonClass)) {
1442+
// Avoid the lookup and call overhead when we know we're calling
1443+
// type.__subclasscheck__
1444+
return genericSubclassCheckNode.execute(frame, inliningTarget, derived, cls);
1445+
}
14451446
try {
1446-
Object instanceCheckResult = subclassCheckNode.executeObject(frame, cls, derived);
1447-
return castToBooleanNode.execute(frame, instanceCheckResult);
1447+
Object result = subclassCheckNode.executeObject(frame, cls, derived);
1448+
return isTrueNode.execute(frame, result);
14481449
} catch (SpecialMethodNotFound ignore) {
1449-
return isSubtypeNode.execute(frame, derived, cls);
1450+
noInstanceCheckProfile.enter(inliningTarget);
1451+
return genericSubclassCheckNode.execute(frame, inliningTarget, derived, cls);
14501452
}
14511453
}
14521454

@@ -1508,9 +1510,7 @@ static Object minmaxSequenceWithKey(VirtualFrame frame, Node inliningTarget, Obj
15081510
@Exclusive @Cached PyObjectRichCompareBool compareNode,
15091511
@Exclusive @Cached PyObjectGetIter getIter,
15101512
@Exclusive @Cached PyIterNextNode nextNode,
1511-
@Exclusive @Cached PyObjectIsTrueNode castToBooleanNode,
15121513
@Exclusive @Cached CallNode.Lazy keyCall,
1513-
@Exclusive @Cached InlinedBranchProfile seenNonBoolean,
15141514
@Exclusive @Cached InlinedConditionProfile keywordArgIsNone,
15151515
@Exclusive @Cached InlinedConditionProfile hasDefaultProfile,
15161516
@Exclusive @Cached PRaiseNode raiseNode) {
@@ -1555,8 +1555,6 @@ static Object minmaxBinaryWithKey(VirtualFrame frame, Node inliningTarget, Objec
15551555
RichCmpOp op,
15561556
@Exclusive @Cached PyObjectRichCompareBool compareNode,
15571557
@Exclusive @Cached CallNode.Lazy keyCall,
1558-
@Exclusive @Cached PyObjectIsTrueNode castToBooleanNode,
1559-
@Exclusive @Cached InlinedBranchProfile seenNonBoolean,
15601558
@Exclusive @Cached InlinedConditionProfile keywordArgIsNone,
15611559
@Exclusive @Cached InlinedConditionProfile moreThanTwo,
15621560
@Exclusive @Cached InlinedLoopConditionProfile loopProfile,

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextModuleBuiltins.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ static Object getName(PythonModule module,
193193
}
194194

195195
static boolean isModuleSubtype(Node inliningTarget, Object obj, GetClassNode getClassNode, IsSubtypeNode isSubtypeNode) {
196-
return isSubtypeNode.execute(null, getClassNode.execute(inliningTarget, obj), PythonBuiltinClassType.PythonModule);
196+
return isSubtypeNode.execute(getClassNode.execute(inliningTarget, obj), PythonBuiltinClassType.PythonModule);
197197
}
198198

199199
@CApiBuiltin(ret = Int, args = {PyObject, ConstCharPtrAsTruffleString, PyObject}, call = Direct)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/BytesNodes.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ static boolean check(Node inliningTarget, PythonAbstractNativeObject obj,
465465
@Cached GetClassNode getClassNode,
466466
@Cached(inline = false) IsSubtypeNode isSubtypeNode) {
467467
Object type = getClassNode.execute(inliningTarget, obj);
468-
return isSubtypeNode.execute(null, type, PythonBuiltinClassType.PBytes) || isSubtypeNode.execute(null, type, PythonBuiltinClassType.PByteArray);
468+
return isSubtypeNode.execute(type, PythonBuiltinClassType.PBytes) || isSubtypeNode.execute(type, PythonBuiltinClassType.PByteArray);
469469
}
470470

471471
@Fallback

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CExtNodes.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -350,23 +350,23 @@ public abstract static class FromNativeSubclassNode extends Node {
350350
public abstract Double execute(VirtualFrame frame, PythonAbstractNativeObject object);
351351

352352
@Specialization
353-
static Double doDouble(VirtualFrame frame, PythonAbstractNativeObject object,
353+
static Double doDouble(PythonAbstractNativeObject object,
354354
@Bind("this") Node inliningTarget,
355355
@Cached GetPythonObjectClassNode getClass,
356356
@Cached IsSubtypeNode isSubtype,
357357
@Cached CStructAccess.ReadDoubleNode read) {
358-
if (isFloatSubtype(frame, inliningTarget, object, getClass, isSubtype)) {
358+
if (isFloatSubtype(inliningTarget, object, getClass, isSubtype)) {
359359
return read.readFromObj(object, PyFloatObject__ob_fval);
360360
}
361361
return null;
362362
}
363363

364-
public static boolean isFloatSubtype(VirtualFrame frame, Node inliningTarget, Object object, GetClassNode getClass, IsSubtypeNode isSubtype) {
365-
return isSubtype.execute(frame, getClass.execute(inliningTarget, object), PythonBuiltinClassType.PFloat);
364+
public static boolean isFloatSubtype(Node inliningTarget, Object object, GetClassNode getClass, IsSubtypeNode isSubtype) {
365+
return isSubtype.execute(getClass.execute(inliningTarget, object), PythonBuiltinClassType.PFloat);
366366
}
367367

368-
public static boolean isFloatSubtype(VirtualFrame frame, Node inliningTarget, PythonAbstractNativeObject object, GetPythonObjectClassNode getClass, IsSubtypeNode isSubtype) {
369-
return isSubtype.execute(frame, getClass.execute(inliningTarget, object), PythonBuiltinClassType.PFloat);
368+
public static boolean isFloatSubtype(Node inliningTarget, PythonAbstractNativeObject object, GetPythonObjectClassNode getClass, IsSubtypeNode isSubtype) {
369+
return isSubtype.execute(getClass.execute(inliningTarget, object), PythonBuiltinClassType.PFloat);
370370
}
371371

372372
@NeverDefault

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/UnicodeDecodeErrorBuiltins.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ public abstract static class PyUnicodeDecodeErrorGetObjectNode extends Node {
215215
public abstract Object execute(Node inliningTarget, PBaseException exceptionObject);
216216

217217
@Specialization
218-
static Object doIt(VirtualFrame frame, Node inliningTarget, PBaseException exceptionObject,
218+
static Object doIt(Node inliningTarget, PBaseException exceptionObject,
219219
@Cached(inline = false) BaseExceptionAttrNode attrNode,
220220
@Cached GetClassNode getClassNode,
221221
@Cached(inline = false) IsSubtypeNode isSubtypeNode,
@@ -224,7 +224,7 @@ static Object doIt(VirtualFrame frame, Node inliningTarget, PBaseException excep
224224
if (obj == null) {
225225
throw raiseNode.raise(inliningTarget, TypeError, ErrorMessages.S_ATTRIBUTE_NOT_SET, "object");
226226
}
227-
if (!isSubtypeNode.execute(frame, getClassNode.execute(inliningTarget, obj), PythonBuiltinClassType.PBytes)) {
227+
if (!isSubtypeNode.execute(getClassNode.execute(inliningTarget, obj), PythonBuiltinClassType.PBytes)) {
228228
throw raiseNode.raise(inliningTarget, TypeError, ErrorMessages.S_ATTRIBUTE_MUST_BE_BYTES, "object");
229229
}
230230
return obj;

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/FloatBuiltins.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ static Object floatFromObjectManagedSubclass(VirtualFrame frame, Object cls, Obj
307307
// floatobject.c we have to first create a temporary float, then fill it into
308308
// a natively allocated subtype structure
309309
@Specialization(guards = {"needsNativeAllocation", //
310-
"isSubtypeOfFloat(frame, isSubtype, cls)"}, limit = "1")
310+
"isSubtypeOfFloat( isSubtype, cls)"}, limit = "1")
311311
@InliningCutoff
312312
static Object floatFromObjectNativeSubclass(VirtualFrame frame, Object cls, Object obj, @SuppressWarnings("unused") boolean needsNativeAllocation,
313313
@Bind("this") @SuppressWarnings("unused") Node inliningTarget,
@@ -317,8 +317,8 @@ static Object floatFromObjectNativeSubclass(VirtualFrame frame, Object cls, Obje
317317
return subtypeNew.call(cls, recursiveCallNode.execute(frame, inliningTarget, obj));
318318
}
319319

320-
protected static boolean isSubtypeOfFloat(VirtualFrame frame, IsSubtypeNode isSubtypeNode, Object cls) {
321-
return isSubtypeNode.execute(frame, cls, PythonBuiltinClassType.PFloat);
320+
protected static boolean isSubtypeOfFloat(IsSubtypeNode isSubtypeNode, Object cls) {
321+
return isSubtypeNode.execute(cls, PythonBuiltinClassType.PFloat);
322322
}
323323
}
324324

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ints/IntBuiltins.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2243,7 +2243,7 @@ static boolean doPP(PInt left, PInt right, RichCmpOp op) {
22432243
return op.compareResultToBool(left.compareTo(right));
22442244
}
22452245

2246-
@Specialization(guards = "isFloatSubtype(frame, inliningTarget, y, getClass, isSubtype)")
2246+
@Specialization(guards = "isFloatSubtype(inliningTarget, y, getClass, isSubtype)")
22472247
@InliningCutoff
22482248
static boolean doDN(VirtualFrame frame, Node inliningTarget, long x, PythonAbstractNativeObject y, RichCmpOp op,
22492249
@SuppressWarnings("unused") @Shared @Cached GetPythonObjectClassNode getClass,
@@ -2253,8 +2253,8 @@ static boolean doDN(VirtualFrame frame, Node inliningTarget, long x, PythonAbstr
22532253
}
22542254

22552255
@Specialization(guards = {
2256-
"isFloatSubtype(frame, inliningTarget, x, getClass, isSubtype)",
2257-
"isFloatSubtype(frame, inliningTarget, y, getClass, isSubtype)"})
2256+
"isFloatSubtype(inliningTarget, x, getClass, isSubtype)",
2257+
"isFloatSubtype(inliningTarget, y, getClass, isSubtype)"})
22582258
@InliningCutoff
22592259
static boolean doDN(VirtualFrame frame, Node inliningTarget, PythonAbstractNativeObject x, PythonAbstractNativeObject y, RichCmpOp op,
22602260
@SuppressWarnings("unused") @Shared @Cached GetPythonObjectClassNode getClass,
@@ -2264,7 +2264,7 @@ static boolean doDN(VirtualFrame frame, Node inliningTarget, PythonAbstractNativ
22642264
return op.compareResultToBool(PFloat.compare(nativeLeft.execute(frame, x), nativeRight.execute(frame, y)));
22652265
}
22662266

2267-
@Specialization(guards = "isFloatSubtype(frame, inliningTarget, x, getClass, isSubtype)")
2267+
@Specialization(guards = "isFloatSubtype(inliningTarget, x, getClass, isSubtype)")
22682268
@InliningCutoff
22692269
static boolean doDN(VirtualFrame frame, Node inliningTarget, PythonAbstractNativeObject x, double y, RichCmpOp op,
22702270
@SuppressWarnings("unused") @Shared @Cached GetPythonObjectClassNode getClass,

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -900,7 +900,7 @@ static Object dir(VirtualFrame frame, Object obj,
900900
PSet names = PFactory.createSet(language);
901901
Object updateCallable = lookupAttrNode.execute(frame, inliningTarget, names, T_UPDATE);
902902
Object ns = lookupAttrNode.execute(frame, inliningTarget, obj, T___DICT__);
903-
if (isSubtypeNode.execute(frame, getClassNode.execute(inliningTarget, ns), PythonBuiltinClassType.PDict)) {
903+
if (isSubtypeNode.execute(getClassNode.execute(inliningTarget, ns), PythonBuiltinClassType.PDict)) {
904904
callNode.execute(frame, updateCallable, ns);
905905
}
906906
Object klass = lookupAttrNode.execute(frame, inliningTarget, obj, T___CLASS__);

0 commit comments

Comments
 (0)