Skip to content

Commit 10c5cc2

Browse files
committed
remove pure flag usage, sanity check tp_traverse
1 parent d970479 commit 10c5cc2

File tree

2 files changed

+26
-19
lines changed

2 files changed

+26
-19
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/hpy/GraalHPyDef.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ public abstract class GraalHPyDef {
124124

125125
public static final HiddenKey TYPE_HPY_ITEMSIZE = new HiddenKey("hpy_itemsize");
126126
public static final HiddenKey TYPE_HPY_FLAGS = new HiddenKey("hpy_flags");
127+
public static final HiddenKey TYPE_HPY_IS_PURE = new HiddenKey("hpy_is_pure");
127128
public static final HiddenKey OBJECT_HPY_NATIVE_SPACE = new HiddenKey("hpy_native_space");
128129

129130
/* enum values of 'HPyDef_Kind' */
@@ -309,8 +310,8 @@ public LLVMType getLLVMFunctionType() {
309310

310311
/* type flags according to 'hpytype.h' */
311312
public static final long _Py_TPFLAGS_HEAPTYPE = (1L << 9);
312-
public static final long HPy_TPFLAGS_INTERNAL_PURE = (1L << 8);
313313
public static final long HPy_TPFLAGS_BASETYPE = (1L << 10);
314+
public static final long HPy_TPFLAGS_HAVE_GC = (1L << 14);
314315
public static final long HPy_TPFLAGS_DEFAULT = _Py_TPFLAGS_HEAPTYPE;
315316

316317
/* enum values for 'HPySlot_Slot' */

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/hpy/GraalHPyNodes.java

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,10 @@
4242

4343
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.SystemError;
4444
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.TypeError;
45+
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.ValueError;
4546
import static com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyDef.HPySlot.HPY_TP_DESTROY;
4647
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;
4749
import static com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyNativeSymbol.GRAAL_HPY_DEF_GET_GETSET;
4850
import static com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyNativeSymbol.GRAAL_HPY_DEF_GET_KIND;
4951
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
730732

731733
/**
732734
* 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.
734736
*
735737
* <pre>
736738
* typedef struct {
@@ -743,10 +745,10 @@ static GetSetDescriptor doIt(GraalHPyContext context, Object type, Object member
743745
@GenerateUncached
744746
public abstract static class HPyCreateSlotNode extends PNodeWithContext {
745747

746-
public abstract HPyProperty execute(GraalHPyContext context, Object enclosingType, Object slotDef);
748+
public abstract Object execute(GraalHPyContext context, Object enclosingType, Object slotDef);
747749

748750
@Specialization(limit = "1")
749-
static HPyProperty doIt(GraalHPyContext context, Object enclosingType, Object slotDef,
751+
static Object doIt(GraalHPyContext context, Object enclosingType, Object slotDef,
750752
@CachedLibrary("slotDef") InteropLibrary interopLibrary,
751753
@CachedLibrary(limit = "2") InteropLibrary resultLib,
752754
@Cached PCallHPyFunction callHelperFunctionNode,
@@ -802,6 +804,9 @@ static HPyProperty doIt(GraalHPyContext context, Object enclosingType, Object sl
802804
if (enclosingType instanceof PythonClass) {
803805
((PythonClass) enclosingType).hpyDestroyFunc = methodFunctionPointer;
804806
}
807+
} else if (HPY_TP_TRAVERSE.equals(slot)) {
808+
assert methodNames.length == 0;
809+
return HPY_TP_TRAVERSE;
805810
} else {
806811
// create properties
807812
for (int i = 0; i < methodNames.length; i++) {
@@ -1933,6 +1938,7 @@ static Object doGeneric(GraalHPyContext context, Object typeSpec, Object typeSpe
19331938
@Cached GetSuperClassNode getSuperClassNode,
19341939
@Cached IsSameTypeNode isSameTypeNode,
19351940
@Cached ReadAttributeFromObjectNode readHPyTypeFlagsNode,
1941+
@Cached ReadAttributeFromObjectNode readHPyIsPureNode,
19361942
@Cached(parameters = "New") LookupCallableSlotInMRONode lookupNewNode,
19371943
@Cached HPyAsPythonObjectNode hPyAsPythonObjectNode,
19381944
@Cached PRaiseNode raiseNode) {
@@ -1978,21 +1984,13 @@ static Object doGeneric(GraalHPyContext context, Object typeSpec, Object typeSpe
19781984

19791985
// store flags, basicsize, and itemsize to type
19801986
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-
19851987
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-
}
19911988

19921989
long basicSize = castToLong(valueLib, ptrLib.readMember(typeSpec, "basicsize"));
19931990
long itemSize = castToLong(valueLib, ptrLib.readMember(typeSpec, "itemsize"));
19941991
writeAttributeToObjectNode.execute(newType, GraalHPyDef.TYPE_HPY_ITEMSIZE, itemSize);
19951992
writeAttributeToObjectNode.execute(newType, GraalHPyDef.TYPE_HPY_FLAGS, flags);
1993+
writeAttributeToObjectNode.execute(newType, GraalHPyDef.TYPE_HPY_IS_PURE, legacy == 0);
19961994
if (newType instanceof PythonClass) {
19971995
PythonClass clazz = (PythonClass) newType;
19981996
clazz.basicSize = basicSize;
@@ -2001,6 +1999,7 @@ static Object doGeneric(GraalHPyContext context, Object typeSpec, Object typeSpe
20011999
}
20022000

20032001
boolean seenNew = false;
2002+
boolean needsTpTraverse = ((flags & GraalHPyDef.HPy_TPFLAGS_HAVE_GC) != 0);
20042003

20052004
// process defines
20062005
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
20232022
break;
20242023
case GraalHPyDef.HPY_DEF_KIND_SLOT:
20252024
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+
}
20272031
if (property != null && SpecialMethodNames.__NEW__.equals(property.key)) {
20282032
seenNew = true;
20292033
}
@@ -2047,6 +2051,10 @@ static Object doGeneric(GraalHPyContext context, Object typeSpec, Object typeSpe
20472051
}
20482052
}
20492053

2054+
if (needsTpTraverse) {
2055+
throw raiseNode.raise(ValueError, "traverse function needed for type with HAVE_GC");
2056+
}
2057+
20502058
// process legacy slots; this is of type 'cpy_PyTypeSlot legacy_slots[]'
20512059
Object legacySlots = callHelperFunctionNode.call(context, GraalHPyNativeSymbol.GRAAL_HPY_TYPE_SPEC_GET_LEGECY_SLOTS, typeSpec);
20522060
if (!ptrLib.isNull(legacySlots)) {
@@ -2089,7 +2097,7 @@ static Object doGeneric(GraalHPyContext context, Object typeSpec, Object typeSpe
20892097
Object baseFlagsObj = readHPyTypeFlagsNode.execute(baseClass, GraalHPyDef.TYPE_HPY_FLAGS);
20902098
baseFlags = baseFlagsObj != PNone.NO_VALUE ? (long) baseFlagsObj : 0;
20912099
}
2092-
checkInheritanceConstraints(flags, baseFlags, raiseNode);
2100+
checkInheritanceConstraints(flags, baseFlags, legacy == 0, readHPyTypeFlagsNode.execute(baseClass, GraalHPyDef.TYPE_HPY_IS_PURE), raiseNode);
20932101

20942102
return newType;
20952103
} catch (CannotCastException | InteropException e) {
@@ -2171,9 +2179,7 @@ private static String[] splitName(String specName) {
21712179
return new String[]{null, specName};
21722180
}
21732181

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) {
21772183
// Pure types may inherit from:
21782184
//
21792185
// * pure types, or
@@ -2184,7 +2190,7 @@ private static void checkInheritanceConstraints(long flags, long baseFlags, PRai
21842190
//
21852191
// It would be nice to relax these restrictions or check them here.
21862192
// See https://github.com/hpyproject/hpy/issues/169 for details.
2187-
if (!isPure && isBasePure) {
2193+
if (!isPure && baseIsPure == Boolean.TRUE) {
21882194
throw raiseNode.raise(TypeError, "A legacy type should not inherit its memory layout from a pure type");
21892195
}
21902196
}

0 commit comments

Comments
 (0)