99
99
import com .oracle .graal .python .nodes .object .GetLazyClassNode ;
100
100
import com .oracle .graal .python .nodes .object .IsBuiltinClassProfile ;
101
101
import com .oracle .graal .python .nodes .truffle .PythonTypes ;
102
+ import com .oracle .graal .python .runtime .exception .PException ;
102
103
import com .oracle .graal .python .runtime .exception .PythonErrorType ;
103
104
import com .oracle .truffle .api .CompilerAsserts ;
104
105
import com .oracle .truffle .api .CompilerDirectives ;
106
+ import com .oracle .truffle .api .CompilerDirectives .CompilationFinal ;
105
107
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
106
108
import com .oracle .truffle .api .dsl .Cached ;
107
109
import com .oracle .truffle .api .dsl .Fallback ;
@@ -529,6 +531,11 @@ public boolean isInstance(Object cls, Object instance) {
529
531
static abstract class SubclassCheckNode extends PythonBinaryBuiltinNode {
530
532
@ Child private IsSubtypeNode isSubtypeNode = IsSubtypeNode .create ();
531
533
@ Child private TypeNodes .IsSameTypeNode isSameTypeNode = TypeNodes .IsSameTypeNode .create ();
534
+ @ Child private GetFixedAttributeNode getBasesAttrNode ;
535
+ @ Child private GetLazyClassNode getClassNode ;
536
+
537
+ @ CompilationFinal private IsBuiltinClassProfile isAttrErrorProfile ;
538
+ @ CompilationFinal private IsBuiltinClassProfile isTupleProfile ;
532
539
533
540
@ Specialization (guards = {"!isNativeClass(cls)" , "!isNativeClass(derived)" })
534
541
boolean doManagedManaged (LazyPythonClass cls , LazyPythonClass derived ) {
@@ -547,15 +554,35 @@ boolean doObjectObject(Object cls, Object derived,
547
554
if (isClsTypeNode .execute (cls ) && isDerivedTypeNode .execute (derived )) {
548
555
return isSubtypeNode .execute (derived , cls );
549
556
}
550
- if (!isDerivedTypeNode . execute (derived )) {
557
+ if (!checkClass (derived )) {
551
558
throw raise (PythonBuiltinClassType .TypeError , "issubclass() arg 1 must be a class" );
552
559
}
553
- if (!isClsTypeNode . execute (cls )) {
560
+ if (!checkClass (cls )) {
554
561
throw raise (PythonBuiltinClassType .TypeError , "issubclass() arg 2 must be a class or tuple of classes" );
555
562
}
556
563
return false ;
557
564
}
558
565
566
+ // checks if object has '__bases__' (see CPython 'abstract.c' function
567
+ // 'recursive_issubclass')
568
+ private boolean checkClass (Object obj ) {
569
+ if (getBasesAttrNode == null || isAttrErrorProfile == null || isTupleProfile == null || getClassNode == null ) {
570
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
571
+ getBasesAttrNode = insert (GetFixedAttributeNode .create (SpecialAttributeNames .__BASES__ ));
572
+ isAttrErrorProfile = IsBuiltinClassProfile .create ();
573
+ isTupleProfile = IsBuiltinClassProfile .create ();
574
+ getClassNode = insert (GetLazyClassNode .create ());
575
+ }
576
+ Object basesObj ;
577
+ try {
578
+ basesObj = getBasesAttrNode .executeObject (obj );
579
+ } catch (PException e ) {
580
+ e .expectAttributeError (isAttrErrorProfile );
581
+ return false ;
582
+ }
583
+ return isTupleProfile .profileClass (getClassNode .execute (basesObj ), PythonBuiltinClassType .PTuple );
584
+ }
585
+
559
586
protected boolean isSameType (Object a , Object b ) {
560
587
return isSameTypeNode .execute (a , b );
561
588
}
0 commit comments