Skip to content

Commit 897faa2

Browse files
committed
[GR-47042] Fix object.__new__ picking up wrong tp_alloc
PullRequest: graalpython/2858
2 parents 19b363d + e900ff7 commit 897faa2

File tree

4 files changed

+46
-70
lines changed

4 files changed

+46
-70
lines changed

graalpython/com.oracle.graal.python.cext/src/capi.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -801,8 +801,8 @@ PyAPI_FUNC(void*) PyTruffle_AsciiToString(void* ptr) {
801801
/* To be used from Java code only.
802802
* This function is used if a native class inherits from a managed class but uses the 'object.__new__'.
803803
* This function roughly corresponds to CPython's 'object_new'. */
804-
PyAPI_FUNC(PyObject*) PyTruffle_Object_New(PyTypeObject* cls, PyTypeObject* dominatingNativeClass, PyObject* args, PyObject* kwds) {
805-
return dominatingNativeClass->tp_alloc(cls, 0);
804+
PyAPI_FUNC(PyObject*) PyTruffle_Object_New(PyTypeObject* cls) {
805+
return cls->tp_alloc(cls, 0);
806806
}
807807

808808
PyAPI_FUNC(void) PyTruffle_PatchType(PyTypeObject* result, PyTypeObject* base) {

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_object.py

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -110,28 +110,30 @@ def test_int(self):
110110
assert int(tester) == 42
111111

112112
def test_inherit_slots_with_managed_class(self):
113-
TestTpAllocWithManaged = CPyExtType("TestTpAllocWithManaged",
114-
"""
115-
static PyObject *test_alloc(PyTypeObject *type, Py_ssize_t nitems) {
116-
PyErr_SetString(PyExc_RuntimeError, "Should not call this tp_alloc");
117-
return NULL;
118-
}
119-
""",
120-
tp_alloc="test_alloc"
113+
ClassWithTpAlloc = CPyExtType(
114+
"ClassWithTpAlloc",
115+
"""
116+
static PyObject *test_alloc(PyTypeObject *type, Py_ssize_t nitems) {
117+
PyErr_SetString(PyExc_RuntimeError, "Should not call this tp_alloc");
118+
return NULL;
119+
}
120+
static PyObject* testslots_tp_alloc(PyObject* self, PyObject *cls) {
121+
return ((PyTypeObject *)cls)->tp_alloc((PyTypeObject *) cls, 0);
122+
}
123+
""",
124+
tp_alloc="test_alloc",
125+
tp_methods='{"call_tp_alloc", (PyCFunction)testslots_tp_alloc, METH_O | METH_STATIC, ""}',
126+
tp_flags='Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC',
127+
tp_free='PyObject_GC_Del',
128+
ready_code="ClassWithTpAllocType.tp_new = PyBaseObject_Type.tp_new;"
121129
)
122-
TestTpAllocCall = CPyExtType("TestTpAllocCall",
123-
'''
124-
static PyObject* testslots_tp_alloc(PyObject* self, PyObject *cls) {
125-
return ((PyTypeObject *)cls)->tp_alloc((PyTypeObject *) cls, 0);
126-
}
127-
''',
128-
tp_methods='{"createObj", (PyCFunction)testslots_tp_alloc, METH_O, ""}'
129-
)
130-
class managed(TestTpAllocWithManaged):
130+
131+
class ManagedSubclass(ClassWithTpAlloc):
131132
pass
132-
t = TestTpAllocCall()
133133

134-
assert t.createObj(managed) != None
134+
assert ClassWithTpAlloc.call_tp_alloc(ManagedSubclass)
135+
assert type(ManagedSubclass()) is ManagedSubclass
136+
assert type(object.__new__(ManagedSubclass)) is ManagedSubclass
135137

136138

137139
def test_float_binops(self):

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

Lines changed: 20 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,10 @@
123123
import com.oracle.graal.python.builtins.objects.cext.PythonNativeVoidPtr;
124124
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes;
125125
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.PCallCapiFunction;
126-
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodesFactory;
127126
import com.oracle.graal.python.builtins.objects.cext.capi.ExternalFunctionNodes;
128127
import com.oracle.graal.python.builtins.objects.cext.capi.NativeCAPISymbol;
129128
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions.NativeToPythonNode;
130129
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions.PythonToNativeNode;
131-
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitionsFactory.NativeToPythonNodeGen;
132130
import com.oracle.graal.python.builtins.objects.cext.common.CArrayWrappers.CByteArrayWrapper;
133131
import com.oracle.graal.python.builtins.objects.code.CodeNodes;
134132
import com.oracle.graal.python.builtins.objects.code.PCode;
@@ -166,15 +164,13 @@
166164
import com.oracle.graal.python.builtins.objects.str.PString;
167165
import com.oracle.graal.python.builtins.objects.traceback.PTraceback;
168166
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
169-
import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass;
170167
import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass;
171168
import com.oracle.graal.python.builtins.objects.type.PythonManagedClass;
172169
import com.oracle.graal.python.builtins.objects.type.SpecialMethodSlot;
173170
import com.oracle.graal.python.builtins.objects.type.TypeBuiltins;
174171
import com.oracle.graal.python.builtins.objects.type.TypeFlags;
175172
import com.oracle.graal.python.builtins.objects.type.TypeNodes;
176173
import com.oracle.graal.python.builtins.objects.type.TypeNodes.CreateTypeNode;
177-
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroNode;
178174
import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsAcceptableBaseNode;
179175
import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsTypeNode;
180176
import com.oracle.graal.python.builtins.objects.types.PGenericAlias;
@@ -1803,13 +1799,9 @@ protected PList constructList(Object cls, @SuppressWarnings("unused") Object[] a
18031799
@GenerateNodeFactory
18041800
public abstract static class ObjectNode extends PythonVarargsBuiltinNode {
18051801

1806-
@Child private PCallCapiFunction callCapiFunction;
1807-
@Children private CExtNodes.ToSulongNode[] toSulongNodes;
1808-
@Child private NativeToPythonNode asPythonObjectNode;
18091802
@Child private SplitArgsNode splitArgsNode;
18101803
@Child private LookupCallableSlotInMRONode lookupInit;
18111804
@Child private LookupCallableSlotInMRONode lookupNew;
1812-
@Child private ReportAbstractClassNode reportAbstractClassNode;
18131805
@CompilationFinal private ValueProfile profileInit;
18141806
@CompilationFinal private ValueProfile profileNew;
18151807
@CompilationFinal private ValueProfile profileInitFactory;
@@ -1867,68 +1859,47 @@ Object doBuiltinTypeType(PythonBuiltinClassType self, Object[] varargs, PKeyword
18671859
@Specialization(guards = "self.needsNativeAllocation()")
18681860
Object doNativeObjectIndirect(VirtualFrame frame, PythonManagedClass self, Object[] varargs, PKeyword[] kwargs,
18691861
@Bind("this") Node inliningTarget,
1870-
@Cached GetMroNode getMroNode,
1871-
@Shared @Cached ReportAbstractClassNode reportAbstractClassNode) {
1862+
@Shared @Cached ReportAbstractClassNode reportAbstractClassNode,
1863+
@Shared @Cached CallNativeGenericNewNode callNativeGenericNewNode) {
18721864
checkExcessArgs(self, varargs, kwargs);
18731865
if (self.isAbstractClass()) {
18741866
throw reportAbstractClassNode.execute(frame, inliningTarget, self);
18751867
}
1876-
Object nativeBaseClass = findFirstNativeBaseClass(getMroNode.execute(self));
1877-
return callNativeGenericNewNode(self, nativeBaseClass, varargs, kwargs);
1868+
return callNativeGenericNewNode.execute(inliningTarget, self);
18781869
}
18791870

18801871
@Specialization(guards = "isNativeClass(self)")
18811872
@SuppressWarnings("truffle-static-method")
18821873
Object doNativeObjectDirect(VirtualFrame frame, Object self, Object[] varargs, PKeyword[] kwargs,
18831874
@Bind("this") Node inliningTarget,
18841875
@Exclusive @Cached TypeNodes.GetTypeFlagsNode getTypeFlagsNode,
1885-
@Shared @Cached ReportAbstractClassNode reportAbstractClassNode) {
1876+
@Shared @Cached ReportAbstractClassNode reportAbstractClassNode,
1877+
@Shared @Cached CallNativeGenericNewNode callNativeGenericNewNode) {
18861878
checkExcessArgs(self, varargs, kwargs);
18871879
if ((getTypeFlagsNode.execute(self) & TypeFlags.IS_ABSTRACT) != 0) {
18881880
throw reportAbstractClassNode.execute(frame, inliningTarget, self);
18891881
}
1890-
return callNativeGenericNewNode(self, self, varargs, kwargs);
1882+
return callNativeGenericNewNode.execute(inliningTarget, self);
18911883
}
18921884

1893-
@SuppressWarnings("unused")
1894-
@Fallback
1895-
Object fallback(Object o, Object[] varargs, PKeyword[] kwargs) {
1896-
throw raise(TypeError, ErrorMessages.IS_NOT_TYPE_OBJ, "object.__new__(X): X", o);
1897-
}
1885+
@GenerateInline
1886+
@GenerateCached(false)
1887+
protected abstract static class CallNativeGenericNewNode extends Node {
1888+
abstract Object execute(Node inliningTarget, Object cls);
18981889

1899-
private static Object findFirstNativeBaseClass(PythonAbstractClass[] methodResolutionOrder) {
1900-
for (Object cls : methodResolutionOrder) {
1901-
if (PGuards.isNativeClass(cls)) {
1902-
return cls;
1903-
}
1890+
@Specialization
1891+
static Object call(Object cls,
1892+
@Cached PythonToNativeNode toNativeNode,
1893+
@Cached NativeToPythonNode toPythonNode,
1894+
@Cached PCallCapiFunction callCapiFunction) {
1895+
return toPythonNode.execute(callCapiFunction.call(FUN_PY_OBJECT_NEW, toNativeNode.execute(cls)));
19041896
}
1905-
CompilerDirectives.transferToInterpreterAndInvalidate();
1906-
throw new IllegalStateException("class needs native allocation but has not native base class");
19071897
}
19081898

1909-
private Object callNativeGenericNewNode(Object type, Object nativeBase, Object[] varargs, PKeyword[] kwargs) {
1910-
if (callCapiFunction == null) {
1911-
CompilerDirectives.transferToInterpreterAndInvalidate();
1912-
callCapiFunction = insert(PCallCapiFunction.create());
1913-
}
1914-
if (toSulongNodes == null) {
1915-
CompilerDirectives.transferToInterpreterAndInvalidate();
1916-
CExtNodes.ToSulongNode[] newToSulongNodes = new CExtNodes.ToSulongNode[4];
1917-
for (int i = 0; i < newToSulongNodes.length; i++) {
1918-
newToSulongNodes[i] = CExtNodesFactory.ToSulongNodeGen.create();
1919-
}
1920-
toSulongNodes = insert(newToSulongNodes);
1921-
}
1922-
if (asPythonObjectNode == null) {
1923-
CompilerDirectives.transferToInterpreterAndInvalidate();
1924-
asPythonObjectNode = insert(NativeToPythonNodeGen.create());
1925-
}
1926-
PKeyword[] kwarr = kwargs.length > 0 ? kwargs : null;
1927-
PTuple targs = factory().createTuple(varargs);
1928-
PDict dkwargs = factory().createDict(kwarr);
1929-
return asPythonObjectNode.execute(
1930-
callCapiFunction.call(FUN_PY_OBJECT_NEW, toSulongNodes[0].execute(type), toSulongNodes[1].execute(nativeBase), toSulongNodes[2].execute(targs),
1931-
toSulongNodes[3].execute(dkwargs)));
1899+
@SuppressWarnings("unused")
1900+
@Fallback
1901+
Object fallback(Object o, Object[] varargs, PKeyword[] kwargs) {
1902+
throw raise(TypeError, ErrorMessages.IS_NOT_TYPE_OBJ, "object.__new__(X): X", o);
19321903
}
19331904

19341905
private void checkExcessArgs(Object type, Object[] varargs, PKeyword[] kwargs) {
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[[rules]]
2+
# Newer versions depend on rpds_py, which needs rust
3+
version = '< 4.18'

0 commit comments

Comments
 (0)