Skip to content

Commit 59d816e

Browse files
committed
PyType_Modified should not modify native slots
1 parent e2820b4 commit 59d816e

File tree

2 files changed

+42
-12
lines changed

2 files changed

+42
-12
lines changed

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

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -598,4 +598,32 @@ def __get__(self,obj,objtype=None): return "dummy"
598598
def __setattr__(self,name,value): return None
599599

600600
assert 3 * Managed1() == 3
601-
assert Managed1() * 3 == "__mul__result: 3"
601+
assert Managed1() * 3 == "__mul__result: 3"
602+
603+
604+
def test_PyType_Modified_doesnt_change_slots():
605+
TypeWithSqItemAndMpSubscr = CPyExtType(
606+
"TypeWithSqItemAndMpSubscr",
607+
code='''
608+
static PyObject* sq_item(PyObject* self, Py_ssize_t index) {
609+
return PyUnicode_FromString("sq_item");
610+
}
611+
static PyObject* mp_subscript(PyObject* self, PyObject* index) {
612+
return PyUnicode_FromString("mp_subscript");
613+
}
614+
static PyObject* call_PySequence_GetItem(PyObject* self, PyObject* index) {
615+
Py_ssize_t i = PyLong_AsSsize_t(index);
616+
if (i == -1 && PyErr_Occurred())
617+
return NULL;
618+
return PySequence_GetItem(self, i);
619+
}
620+
''',
621+
sq_item="sq_item",
622+
mp_subscript="mp_subscript",
623+
tp_methods='{"call_PySequence_GetItem", (PyCFunction)call_PySequence_GetItem, METH_O, ""}',
624+
post_ready_code="PyType_Modified(&TypeWithSqItemAndMpSubscrType);"
625+
)
626+
tester = TypeWithSqItemAndMpSubscr()
627+
assert tester[1] == 'mp_subscript'
628+
assert tester.call_PySequence_GetItem(1) == 'sq_item'
629+

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

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
import com.oracle.graal.python.nodes.attributes.WriteAttributeToPythonObjectNode;
104104
import com.oracle.graal.python.nodes.object.GetDictIfExistsNode;
105105
import com.oracle.graal.python.nodes.util.CastToTruffleStringNode;
106+
import com.oracle.graal.python.runtime.PythonContext;
106107
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
107108
import com.oracle.graal.python.runtime.sequence.storage.MroSequenceStorage;
108109
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
@@ -127,7 +128,6 @@
127128
import com.oracle.truffle.api.object.DynamicObject;
128129
import com.oracle.truffle.api.object.DynamicObjectLibrary;
129130
import com.oracle.truffle.api.object.Shape;
130-
import com.oracle.truffle.api.profiles.InlinedExactClassProfile;
131131
import com.oracle.truffle.api.strings.TruffleString;
132132
import com.oracle.truffle.api.utilities.CyclicAssumption;
133133

@@ -222,12 +222,14 @@ abstract static class PyTruffle_Type_Modified extends CApiTernaryBuiltinNode {
222222

223223
@TruffleBoundary
224224
@Specialization(guards = "isNoValue(mroTuple)")
225-
int doIt(PythonNativeClass clazz, TruffleString name, @SuppressWarnings("unused") PNone mroTuple) {
226-
CyclicAssumption nativeClassStableAssumption = getContext().getNativeClassStableAssumption(clazz, false);
225+
static int doIt(PythonAbstractNativeObject clazz, TruffleString name, @SuppressWarnings("unused") PNone mroTuple,
226+
@Bind("this") Node inliningTarget) {
227+
PythonContext context = PythonContext.get(inliningTarget);
228+
CyclicAssumption nativeClassStableAssumption = context.getNativeClassStableAssumption(clazz, false);
227229
if (nativeClassStableAssumption != null) {
228230
nativeClassStableAssumption.invalidate("PyType_Modified(\"" + name.toJavaStringUncached() + "\") (without MRO) called");
229231
}
230-
SpecialMethodSlot.reinitializeSpecialMethodSlots(PythonNativeClass.cast(clazz), getLanguage());
232+
SpecialMethodSlot.reinitializeSpecialMethodSlots(clazz, context.getLanguage());
231233
// TODO: this is called from two places: at the end of PyType_Ready, and theoretically
232234
// could be called from:
233235
//
@@ -243,22 +245,22 @@ int doIt(PythonNativeClass clazz, TruffleString name, @SuppressWarnings("unused"
243245

244246
@TruffleBoundary
245247
@Specialization
246-
int doIt(PythonNativeClass clazz, TruffleString name, PTuple mroTuple,
247-
@Bind("this") Node inliningTarget,
248-
@Cached InlinedExactClassProfile profile) {
249-
CyclicAssumption nativeClassStableAssumption = getContext().getNativeClassStableAssumption(clazz, false);
248+
static int doIt(PythonAbstractNativeObject clazz, TruffleString name, PTuple mroTuple,
249+
@Bind("this") Node inliningTarget) {
250+
PythonContext context = PythonContext.get(inliningTarget);
251+
CyclicAssumption nativeClassStableAssumption = context.getNativeClassStableAssumption(clazz, false);
250252
if (nativeClassStableAssumption != null) {
251253
nativeClassStableAssumption.invalidate("PyType_Modified(\"" + name.toJavaStringUncached() + "\") called");
252254
}
253-
SequenceStorage sequenceStorage = profile.profile(inliningTarget, mroTuple.getSequenceStorage());
255+
SequenceStorage sequenceStorage = mroTuple.getSequenceStorage();
254256
if (sequenceStorage instanceof MroSequenceStorage) {
255257
((MroSequenceStorage) sequenceStorage).lookupChanged();
256258
} else {
257259
CompilerDirectives.transferToInterpreterAndInvalidate();
258260
throw new IllegalStateException("invalid MRO object for native type \"" + name.toJavaStringUncached() + "\"");
259261
}
260-
SpecialMethodSlot.reinitializeSpecialMethodSlots(PythonNativeClass.cast(clazz), getLanguage());
261-
TpSlots.updateAllSlots(clazz);
262+
SpecialMethodSlot.reinitializeSpecialMethodSlots(PythonNativeClass.cast(clazz), context.getLanguage());
263+
clazz.setTpSlots(TpSlots.fromNative(clazz, context));
262264
return 0;
263265
}
264266
}

0 commit comments

Comments
 (0)