42
42
43
43
import static com .oracle .graal .python .builtins .PythonBuiltinClassType .SystemError ;
44
44
import static com .oracle .graal .python .builtins .PythonBuiltinClassType .TypeError ;
45
+ import static com .oracle .graal .python .builtins .PythonBuiltinClassType .ValueError ;
45
46
import static com .oracle .graal .python .builtins .objects .cext .hpy .GraalHPyDef .HPySlot .HPY_TP_DESTROY ;
46
47
import static com .oracle .graal .python .builtins .objects .cext .hpy .GraalHPyDef .HPySlot .HPY_TP_NEW ;
48
+ import static com .oracle .graal .python .builtins .objects .cext .hpy .GraalHPyDef .HPySlot .HPY_TP_TRAVERSE ;
47
49
import static com .oracle .graal .python .builtins .objects .cext .hpy .GraalHPyNativeSymbol .GRAAL_HPY_DEF_GET_GETSET ;
48
50
import static com .oracle .graal .python .builtins .objects .cext .hpy .GraalHPyNativeSymbol .GRAAL_HPY_DEF_GET_KIND ;
49
51
import static com .oracle .graal .python .builtins .objects .cext .hpy .GraalHPyNativeSymbol .GRAAL_HPY_DEF_GET_MEMBER ;
@@ -730,7 +732,7 @@ static GetSetDescriptor doIt(GraalHPyContext context, Object type, Object member
730
732
731
733
/**
732
734
* Parser an {@code HPySlot} structure, creates and adds the appropriate function as magic
733
- * method.
735
+ * method. Returns either an HPyProperty if created, or the HPySlot itself.
734
736
*
735
737
* <pre>
736
738
* typedef struct {
@@ -743,10 +745,10 @@ static GetSetDescriptor doIt(GraalHPyContext context, Object type, Object member
743
745
@ GenerateUncached
744
746
public abstract static class HPyCreateSlotNode extends PNodeWithContext {
745
747
746
- public abstract HPyProperty execute (GraalHPyContext context , Object enclosingType , Object slotDef );
748
+ public abstract Object execute (GraalHPyContext context , Object enclosingType , Object slotDef );
747
749
748
750
@ Specialization (limit = "1" )
749
- static HPyProperty doIt (GraalHPyContext context , Object enclosingType , Object slotDef ,
751
+ static Object doIt (GraalHPyContext context , Object enclosingType , Object slotDef ,
750
752
@ CachedLibrary ("slotDef" ) InteropLibrary interopLibrary ,
751
753
@ CachedLibrary (limit = "2" ) InteropLibrary resultLib ,
752
754
@ Cached PCallHPyFunction callHelperFunctionNode ,
@@ -802,6 +804,9 @@ static HPyProperty doIt(GraalHPyContext context, Object enclosingType, Object sl
802
804
if (enclosingType instanceof PythonClass ) {
803
805
((PythonClass ) enclosingType ).hpyDestroyFunc = methodFunctionPointer ;
804
806
}
807
+ } else if (HPY_TP_TRAVERSE .equals (slot )) {
808
+ assert methodNames .length == 0 ;
809
+ return HPY_TP_TRAVERSE ;
805
810
} else {
806
811
// create properties
807
812
for (int i = 0 ; i < methodNames .length ; i ++) {
@@ -1933,6 +1938,7 @@ static Object doGeneric(GraalHPyContext context, Object typeSpec, Object typeSpe
1933
1938
@ Cached GetSuperClassNode getSuperClassNode ,
1934
1939
@ Cached IsSameTypeNode isSameTypeNode ,
1935
1940
@ Cached ReadAttributeFromObjectNode readHPyTypeFlagsNode ,
1941
+ @ Cached ReadAttributeFromObjectNode readHPyIsPureNode ,
1936
1942
@ Cached (parameters = "New" ) LookupCallableSlotInMRONode lookupNewNode ,
1937
1943
@ Cached HPyAsPythonObjectNode hPyAsPythonObjectNode ,
1938
1944
@ Cached PRaiseNode raiseNode ) {
@@ -1978,21 +1984,13 @@ static Object doGeneric(GraalHPyContext context, Object typeSpec, Object typeSpe
1978
1984
1979
1985
// store flags, basicsize, and itemsize to type
1980
1986
long flags = castToLong (valueLib , ptrLib .readMember (typeSpec , "flags" ));
1981
- if ((flags & GraalHPyDef .HPy_TPFLAGS_INTERNAL_PURE ) != 0 ) {
1982
- throw raiseNode .raise (TypeError , "HPy_TPFLAGS_INTERNAL_PURE should not be used directly, set .legacy=true instead" );
1983
- }
1984
-
1985
1987
long legacy = castToLong (valueLib , ptrLib .readMember (typeSpec , "legacy" ));
1986
- if (legacy != 0 ) {
1987
- flags &= ~GraalHPyDef .HPy_TPFLAGS_INTERNAL_PURE ;
1988
- } else {
1989
- flags |= GraalHPyDef .HPy_TPFLAGS_INTERNAL_PURE ;
1990
- }
1991
1988
1992
1989
long basicSize = castToLong (valueLib , ptrLib .readMember (typeSpec , "basicsize" ));
1993
1990
long itemSize = castToLong (valueLib , ptrLib .readMember (typeSpec , "itemsize" ));
1994
1991
writeAttributeToObjectNode .execute (newType , GraalHPyDef .TYPE_HPY_ITEMSIZE , itemSize );
1995
1992
writeAttributeToObjectNode .execute (newType , GraalHPyDef .TYPE_HPY_FLAGS , flags );
1993
+ writeAttributeToObjectNode .execute (newType , GraalHPyDef .TYPE_HPY_IS_PURE , legacy == 0 );
1996
1994
if (newType instanceof PythonClass ) {
1997
1995
PythonClass clazz = (PythonClass ) newType ;
1998
1996
clazz .basicSize = basicSize ;
@@ -2001,6 +1999,7 @@ static Object doGeneric(GraalHPyContext context, Object typeSpec, Object typeSpe
2001
1999
}
2002
2000
2003
2001
boolean seenNew = false ;
2002
+ boolean needsTpTraverse = ((flags & GraalHPyDef .HPy_TPFLAGS_HAVE_GC ) != 0 );
2004
2003
2005
2004
// process defines
2006
2005
Object defines = callHelperFunctionNode .call (context , GraalHPyNativeSymbol .GRAAL_HPY_TYPE_SPEC_GET_DEFINES , typeSpec );
@@ -2023,7 +2022,12 @@ static Object doGeneric(GraalHPyContext context, Object typeSpec, Object typeSpe
2023
2022
break ;
2024
2023
case GraalHPyDef .HPY_DEF_KIND_SLOT :
2025
2024
Object slotDef = callHelperFunctionNode .call (context , GRAAL_HPY_DEF_GET_SLOT , moduleDefine );
2026
- property = addSlotNode .execute (context , newType , slotDef );
2025
+ Object addSlotResult = addSlotNode .execute (context , newType , slotDef );
2026
+ if (HPY_TP_TRAVERSE .equals (addSlotResult )) {
2027
+ needsTpTraverse = false ;
2028
+ } else if (addSlotResult instanceof HPyProperty ) {
2029
+ property = (HPyProperty ) addSlotResult ;
2030
+ }
2027
2031
if (property != null && SpecialMethodNames .__NEW__ .equals (property .key )) {
2028
2032
seenNew = true ;
2029
2033
}
@@ -2047,6 +2051,10 @@ static Object doGeneric(GraalHPyContext context, Object typeSpec, Object typeSpe
2047
2051
}
2048
2052
}
2049
2053
2054
+ if (needsTpTraverse ) {
2055
+ throw raiseNode .raise (ValueError , "traverse function needed for type with HAVE_GC" );
2056
+ }
2057
+
2050
2058
// process legacy slots; this is of type 'cpy_PyTypeSlot legacy_slots[]'
2051
2059
Object legacySlots = callHelperFunctionNode .call (context , GraalHPyNativeSymbol .GRAAL_HPY_TYPE_SPEC_GET_LEGECY_SLOTS , typeSpec );
2052
2060
if (!ptrLib .isNull (legacySlots )) {
@@ -2089,7 +2097,7 @@ static Object doGeneric(GraalHPyContext context, Object typeSpec, Object typeSpe
2089
2097
Object baseFlagsObj = readHPyTypeFlagsNode .execute (baseClass , GraalHPyDef .TYPE_HPY_FLAGS );
2090
2098
baseFlags = baseFlagsObj != PNone .NO_VALUE ? (long ) baseFlagsObj : 0 ;
2091
2099
}
2092
- checkInheritanceConstraints (flags , baseFlags , raiseNode );
2100
+ checkInheritanceConstraints (flags , baseFlags , legacy == 0 , readHPyTypeFlagsNode . execute ( baseClass , GraalHPyDef . TYPE_HPY_IS_PURE ), raiseNode );
2093
2101
2094
2102
return newType ;
2095
2103
} catch (CannotCastException | InteropException e ) {
@@ -2171,9 +2179,7 @@ private static String[] splitName(String specName) {
2171
2179
return new String []{null , specName };
2172
2180
}
2173
2181
2174
- private static void checkInheritanceConstraints (long flags , long baseFlags , PRaiseNode raiseNode ) {
2175
- boolean isPure = (flags & GraalHPyDef .HPy_TPFLAGS_INTERNAL_PURE ) != 0 ;
2176
- boolean isBasePure = (baseFlags & GraalHPyDef .HPy_TPFLAGS_INTERNAL_PURE ) != 0 ;
2182
+ private static void checkInheritanceConstraints (long flags , long baseFlags , boolean isPure , Object baseIsPure , PRaiseNode raiseNode ) {
2177
2183
// Pure types may inherit from:
2178
2184
//
2179
2185
// * pure types, or
@@ -2184,7 +2190,7 @@ private static void checkInheritanceConstraints(long flags, long baseFlags, PRai
2184
2190
//
2185
2191
// It would be nice to relax these restrictions or check them here.
2186
2192
// See https://github.com/hpyproject/hpy/issues/169 for details.
2187
- if (!isPure && isBasePure ) {
2193
+ if (!isPure && baseIsPure == Boolean . TRUE ) {
2188
2194
throw raiseNode .raise (TypeError , "A legacy type should not inherit its memory layout from a pure type" );
2189
2195
}
2190
2196
}
0 commit comments