Skip to content

Commit fd39d61

Browse files
committed
Refactor PyObjectSetAttr/O and TpSlotSetAttr
PyObjectSetAttr/O and the SetattrWrapper are the only direct users of TpSlotSetAttr. Other GraalPy code sets attributes via PyObjectSetAttr/O.
1 parent ea13231 commit fd39d61

File tree

15 files changed

+171
-72
lines changed

15 files changed

+171
-72
lines changed

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

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,37 @@ def __getattr__(self, item):
166166
assert x.foo is None
167167

168168

169+
def test_setattr_str_subclass():
170+
TestAttrSetWitStrSubclass = CPyExtType("TestAttrSetWitStrSubclass",
171+
'''
172+
int testattro_set(PyObject* self, PyObject* key, PyObject* value) {
173+
Py_XDECREF(((TestAttrSetWitStrSubclassObject*)self)->payload);
174+
if (key != NULL) {
175+
Py_INCREF(key);
176+
}
177+
((TestAttrSetWitStrSubclassObject*)self)->payload = key;
178+
return 0;
179+
}
180+
181+
PyObject* my_repr(PyObject *self) {
182+
PyObject* r = ((TestAttrSetWitStrSubclassObject*)self)->payload;
183+
if (r == NULL) Py_RETURN_NONE;
184+
Py_INCREF(r);
185+
return r;
186+
}
187+
''',
188+
cmembers='PyObject* payload;',
189+
tp_repr="my_repr",
190+
tp_setattro="(setattrofunc) testattro_set")
191+
class MyStr(str):
192+
pass
193+
194+
x = TestAttrSetWitStrSubclass()
195+
setattr(x, MyStr('hello'), 42)
196+
assert type(repr(x)) == MyStr
197+
assert repr(x) == 'hello'
198+
199+
169200
def test_concat_vs_add():
170201
# Inheritance of the Py_sq_concat slot:
171202
SqAdd = CPyExtHeapType("SqAdd",
@@ -251,32 +282,32 @@ def test_type_not_ready():
251282
module = compile_module_from_string("""
252283
#define PY_SSIZE_T_CLEAN
253284
#include <Python.h>
254-
285+
255286
static PyObject* my_getattro(PyObject* self, PyObject* key) {
256287
return Py_NewRef(key);
257288
}
258-
289+
259290
static PyTypeObject NotReadyType = {
260291
PyVarObject_HEAD_INIT(NULL, 0)
261292
.tp_name = "NotReadyType",
262293
.tp_basicsize = sizeof(PyObject),
263294
.tp_dealloc = (destructor)PyObject_Del,
264295
.tp_getattro = my_getattro
265296
};
266-
297+
267298
static PyObject* create_not_ready(PyObject* module, PyObject* unused) {
268299
return PyObject_New(PyObject, &NotReadyType);
269300
}
270-
301+
271302
static PyMethodDef module_methods[] = {
272303
{"create_not_ready", _PyCFunction_CAST(create_not_ready), METH_NOARGS, ""},
273304
{NULL}
274305
};
275-
306+
276307
static PyModuleDef NotReadyTypeModule = {
277308
PyModuleDef_HEAD_INIT, "NotReadyType", "", -1, module_methods
278309
};
279-
310+
280311
PyMODINIT_FUNC
281312
PyInit_NotReadyType(void)
282313
{

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@
179179
import com.oracle.graal.python.lib.PyObjectLookupAttr;
180180
import com.oracle.graal.python.lib.PyObjectLookupAttrO;
181181
import com.oracle.graal.python.lib.PyObjectReprAsObjectNode;
182+
import com.oracle.graal.python.lib.PyObjectSetAttrO;
182183
import com.oracle.graal.python.lib.PyObjectSetItem;
183184
import com.oracle.graal.python.lib.PyObjectSizeNode;
184185
import com.oracle.graal.python.lib.PyObjectStrAsObjectNode;
@@ -198,7 +199,6 @@
198199
import com.oracle.graal.python.nodes.attributes.GetAttributeNode;
199200
import com.oracle.graal.python.nodes.attributes.LookupCallableSlotInMRONode;
200201
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode;
201-
import com.oracle.graal.python.nodes.attributes.SetAttributeNode;
202202
import com.oracle.graal.python.nodes.builtins.ListNodes;
203203
import com.oracle.graal.python.nodes.builtins.ListNodes.ConstructListNode;
204204
import com.oracle.graal.python.nodes.bytecode.GetAIterNode;
@@ -2079,9 +2079,10 @@ static Object round(VirtualFrame frame, Object x, Object n,
20792079
@GenerateNodeFactory
20802080
public abstract static class SetAttrNode extends PythonTernaryBuiltinNode {
20812081
@Specialization
2082-
Object setAttr(VirtualFrame frame, Object object, Object key, Object value,
2083-
@Cached SetAttributeNode.Dynamic setAttrNode) {
2084-
setAttrNode.execute(frame, object, key, value);
2082+
static Object setAttr(VirtualFrame frame, Object object, Object key, Object value,
2083+
@Bind("this") Node inliningTarget,
2084+
@Cached PyObjectSetAttrO setAttrNode) {
2085+
setAttrNode.execute(frame, inliningTarget, object, key, value);
20852086
return PNone.NONE;
20862087
}
20872088
}

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

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,12 @@
8484
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetBaseClassNode;
8585
import com.oracle.graal.python.lib.PyObjectCallMethodObjArgs;
8686
import com.oracle.graal.python.lib.PyObjectGetAttr;
87+
import com.oracle.graal.python.lib.PyObjectSetAttr;
8788
import com.oracle.graal.python.lib.PyObjectStrAsTruffleStringNode;
8889
import com.oracle.graal.python.nodes.BuiltinNames;
8990
import com.oracle.graal.python.nodes.PGuards;
9091
import com.oracle.graal.python.nodes.PNodeWithContext;
9192
import com.oracle.graal.python.nodes.PRaiseNode;
92-
import com.oracle.graal.python.nodes.attributes.SetAttributeNode;
9393
import com.oracle.graal.python.nodes.call.CallNode;
9494
import com.oracle.graal.python.nodes.call.special.CallVarargsMethodNode;
9595
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
@@ -110,7 +110,6 @@
110110
import com.oracle.truffle.api.dsl.GenerateInline;
111111
import com.oracle.truffle.api.dsl.GenerateUncached;
112112
import com.oracle.truffle.api.dsl.ImportStatic;
113-
import com.oracle.truffle.api.dsl.NeverDefault;
114113
import com.oracle.truffle.api.dsl.NodeFactory;
115114
import com.oracle.truffle.api.dsl.Specialization;
116115
import com.oracle.truffle.api.frame.Frame;
@@ -326,7 +325,7 @@ protected abstract static class CodecInitNode extends PythonVarargsBuiltinNode {
326325
Object init(VirtualFrame frame, PythonObject self, Object[] args, PKeyword[] kw,
327326
@Bind("this") Node inliningTarget,
328327
@Cached PyObjectGetAttr getAttrNode,
329-
@Cached("createSetAttr()") SetAttributeNode setAttrNode,
328+
@Cached PyObjectSetAttr setAttrNode,
330329
@Cached GetPythonObjectClassNode getClass,
331330
@Cached GetBaseClassNode getBaseClassNode,
332331
@Cached CallNode callNode) {
@@ -339,14 +338,9 @@ Object init(VirtualFrame frame, PythonObject self, Object[] args, PKeyword[] kw,
339338
PythonUtils.arraycopy(args, 1, callArgs, 1, args.length - 1);
340339
}
341340
callNode.execute(frame, superInit, callArgs, kw);
342-
setAttrNode.execute(frame, self, args[0]);
341+
setAttrNode.execute(frame, inliningTarget, self, T_ATTR_ENCODING, args[0]);
343342
return PNone.NONE;
344343
}
345-
346-
@NeverDefault
347-
protected SetAttributeNode createSetAttr() {
348-
return SetAttributeNode.create(T_ATTR_ENCODING);
349-
}
350344
}
351345

352346
@Builtin(name = J___CALL__, minNumOfPositionalArgs = 1, takesVarArgs = true, takesVarKeywordArgs = true)

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import static com.oracle.graal.python.builtins.modules.ImpModuleBuiltins.FrozenStatus.FROZEN_INVALID;
4747
import static com.oracle.graal.python.builtins.modules.ImpModuleBuiltins.FrozenStatus.FROZEN_NOT_FOUND;
4848
import static com.oracle.graal.python.builtins.modules.ImpModuleBuiltins.FrozenStatus.FROZEN_OKAY;
49+
import static com.oracle.graal.python.nodes.SpecialAttributeNames.T___LOADER__;
4950
import static com.oracle.graal.python.nodes.SpecialAttributeNames.T___ORIGNAME__;
5051
import static com.oracle.graal.python.nodes.SpecialAttributeNames.T___PATH__;
5152
import static com.oracle.graal.python.nodes.StringLiterals.T_EXT_PYD;
@@ -95,13 +96,13 @@
9596
import com.oracle.graal.python.builtins.objects.str.PString;
9697
import com.oracle.graal.python.compiler.Compiler;
9798
import com.oracle.graal.python.lib.PyObjectLookupAttr;
99+
import com.oracle.graal.python.lib.PyObjectSetAttr;
98100
import com.oracle.graal.python.lib.PyObjectStrAsTruffleStringNode;
99101
import com.oracle.graal.python.nodes.ErrorMessages;
100102
import com.oracle.graal.python.nodes.PConstructAndRaiseNode;
101103
import com.oracle.graal.python.nodes.PGuards;
102104
import com.oracle.graal.python.nodes.PRaiseNode;
103105
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromPythonObjectNode;
104-
import com.oracle.graal.python.nodes.attributes.SetAttributeNode;
105106
import com.oracle.graal.python.nodes.attributes.WriteAttributeToPythonObjectNode;
106107
import com.oracle.graal.python.nodes.call.GenericInvokeNode;
107108
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
@@ -432,7 +433,7 @@ public abstract static class CreateBuiltin extends PythonBuiltinNode {
432433
static Object run(VirtualFrame frame, PythonObject moduleSpec,
433434
@Bind("this") Node inliningTarget,
434435
@Cached CastToTruffleStringNode toStringNode,
435-
@Cached("create(T___LOADER__)") SetAttributeNode setAttributeNode,
436+
@Cached PyObjectSetAttr setAttributeNode,
436437
@Cached PyObjectLookupAttr lookup) {
437438
Object name = lookup.execute(frame, inliningTarget, moduleSpec, T_NAME);
438439
PythonModule builtinModule = PythonContext.get(inliningTarget).lookupBuiltinModule(toStringNode.execute(inliningTarget, name));
@@ -443,7 +444,7 @@ static Object run(VirtualFrame frame, PythonObject moduleSpec,
443444
// reinitialization (if reinit is possible)
444445
Object loader = lookup.execute(frame, inliningTarget, moduleSpec, T_LOADER);
445446
if (loader != PNone.NO_VALUE) {
446-
setAttributeNode.execute(frame, builtinModule, loader);
447+
setAttributeNode.execute(frame, inliningTarget, builtinModule, T___LOADER__, loader);
447448
}
448449
return builtinModule;
449450
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/PyCSimpleTypeBuiltins.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,9 @@
8585
import com.oracle.graal.python.builtins.objects.str.StringUtils;
8686
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetBaseClassNode;
8787
import com.oracle.graal.python.lib.PyObjectLookupAttr;
88+
import com.oracle.graal.python.lib.PyObjectSetAttr;
8889
import com.oracle.graal.python.nodes.PGuards;
8990
import com.oracle.graal.python.nodes.PRaiseNode;
90-
import com.oracle.graal.python.nodes.attributes.SetAttributeNode;
9191
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
9292
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
9393
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
@@ -146,7 +146,7 @@ static Object PyCSimpleType_new(VirtualFrame frame, Object type, Object[] args,
146146
@Cached PyObjectLookupAttr lookupAttrType,
147147
@Cached GetBaseClassNode getBaseClassNode,
148148
@Cached CastToTruffleStringNode toTruffleStringNode,
149-
@Cached SetAttributeNode.DynamicStringKey setAttrString,
149+
@Cached PyObjectSetAttr setAttrString,
150150
@Cached PyTypeStgDictNode pyTypeStgDictNode,
151151
@Cached TruffleString.IndexOfStringNode indexOfStringNode,
152152
@Cached TruffleString.CodePointAtIndexNode codePointAtIndexNode,
@@ -245,10 +245,10 @@ static Object PyCSimpleType_new(VirtualFrame frame, Object type, Object[] args,
245245
addAllToOtherNode,
246246
factory);
247247
StgDictObject sw_dict = pyTypeStgDictNode.execute(inliningTarget, swapped);
248-
setAttrString.execute(frame, result, T_CTYPE_BE, swapped);
249-
setAttrString.execute(frame, result, T_CTYPE_LE, result);
250-
setAttrString.execute(frame, swapped, T_CTYPE_LE, result);
251-
setAttrString.execute(frame, swapped, T_CTYPE_BE, swapped);
248+
setAttrString.execute(frame, inliningTarget, result, T_CTYPE_BE, swapped);
249+
setAttrString.execute(frame, inliningTarget, result, T_CTYPE_LE, result);
250+
setAttrString.execute(frame, inliningTarget, swapped, T_CTYPE_LE, result);
251+
setAttrString.execute(frame, inliningTarget, swapped, T_CTYPE_BE, swapped);
252252
/* We are creating the type for the OTHER endian */
253253
sw_dict.format = switchEncodingNode.execute(fromCharArrayNode.execute(new char[]{'>', (char) codePointAtIndexNode.execute(stgdict.format, 1, TS_ENCODING)}), TS_ENCODING);
254254
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/StgDictBuiltins.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,14 @@
7373
import com.oracle.graal.python.lib.PyObjectGetAttrO;
7474
import com.oracle.graal.python.lib.PyObjectGetItem;
7575
import com.oracle.graal.python.lib.PyObjectLookupAttr;
76+
import com.oracle.graal.python.lib.PyObjectSetAttrO;
7677
import com.oracle.graal.python.lib.PyObjectSizeNode;
7778
import com.oracle.graal.python.lib.PySequenceCheckNode;
7879
import com.oracle.graal.python.nodes.PGuards;
7980
import com.oracle.graal.python.nodes.PNodeWithContext;
8081
import com.oracle.graal.python.nodes.PRaiseNode;
8182
import com.oracle.graal.python.nodes.SpecialMethodNames;
8283
import com.oracle.graal.python.nodes.attributes.GetAttributeNode;
83-
import com.oracle.graal.python.nodes.attributes.SetAttributeNode;
8484
import com.oracle.graal.python.nodes.call.CallNode;
8585
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
8686
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
@@ -189,7 +189,7 @@ static void MakeFields(VirtualFrame frame, Object type, CFieldObject descr, int
189189
@Bind("this") Node inliningTarget,
190190
@Cached GetClassNode getClassNode,
191191
@Cached PyObjectGetAttrO getAttributeNode,
192-
@Cached SetAttributeNode.Dynamic setAttributeNode,
192+
@Cached PyObjectSetAttrO setAttributeNode,
193193
@Cached PySequenceCheckNode sequenceCheckNode,
194194
@Cached PyObjectSizeNode sizeNode,
195195
@Cached PyObjectGetItem getItemNode,
@@ -235,7 +235,7 @@ static void MakeFields(VirtualFrame frame, Object type, CFieldObject descr, int
235235
new_descr.getfunc = fdescr.getfunc;
236236
new_descr.setfunc = fdescr.setfunc;
237237

238-
setAttributeNode.execute(frame, type, fname, new_descr);
238+
setAttributeNode.execute(frame, inliningTarget, type, fname, new_descr);
239239
}
240240
}
241241

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/StructUnionTypeBuiltins.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -92,10 +92,11 @@
9292
import com.oracle.graal.python.lib.PyNumberAsSizeNode;
9393
import com.oracle.graal.python.lib.PyObjectGetItem;
9494
import com.oracle.graal.python.lib.PyObjectLookupAttr;
95+
import com.oracle.graal.python.lib.PyObjectSetAttr;
96+
import com.oracle.graal.python.lib.PyObjectSetAttrO;
9597
import com.oracle.graal.python.lib.PyObjectSizeNode;
9698
import com.oracle.graal.python.nodes.PGuards;
9799
import com.oracle.graal.python.nodes.PRaiseNode;
98-
import com.oracle.graal.python.nodes.attributes.SetAttributeNode;
99100
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
100101
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
101102
import com.oracle.graal.python.nodes.object.BuiltinClassProfiles.IsBuiltinObjectProfile;
@@ -154,7 +155,7 @@ protected Object StructUnionTypeNew(VirtualFrame frame, Object type, Object[] ar
154155
@Cached GetDictIfExistsNode getDict,
155156
@Cached SetDictNode setDict,
156157
@Cached GetBaseClassNode getBaseClassNode,
157-
@Cached("create(T__FIELDS_)") SetAttributeNode setFieldsAttributeNode,
158+
@Cached PyObjectSetAttr setFieldsAttributeNode,
158159
@Cached PythonObjectFactory factory) {
159160
/*
160161
* create the new instance (which is a class, since we are a metatype!)
@@ -184,7 +185,7 @@ protected Object StructUnionTypeNew(VirtualFrame frame, Object type, Object[] ar
184185
dict.paramfunc = CArgObjectBuiltins.StructUnionTypeParamFunc;
185186
Object fieldsValue = getItemStgDict.execute(inliningTarget, dict.getDictStorage(), T__FIELDS_);
186187
if (fieldsValue != null) {
187-
setFieldsAttributeNode.execute(frame, result, fieldsValue);
188+
setFieldsAttributeNode.execute(frame, inliningTarget, result, T__FIELDS_, fieldsValue);
188189
} else {
189190
StgDictObject basedict = pyTypeStgDictNode.execute(inliningTarget, getBaseClassNode.execute(inliningTarget, result));
190191
if (basedict == null) {
@@ -224,7 +225,7 @@ static void PyCStructUnionType_update_stgdict(VirtualFrame frame, Object type, O
224225
@Cached GetBaseClassNode getBaseClassNode,
225226
@Cached MakeAnonFieldsNode makeAnonFieldsNode,
226227
@Cached PyNumberAsSizeNode asSizeNode,
227-
@Cached SetAttributeNode.Dynamic setAttr,
228+
@Cached PyObjectSetAttrO setAttr,
228229
@Cached IsBuiltinObjectProfile isBuiltinClassProfile,
229230
@Cached PyObjectLookupAttr lookupSwappedbytes,
230231
@Cached PyObjectLookupAttr lookupPack,
@@ -434,7 +435,7 @@ static void PyCStructUnionType_update_stgdict(VirtualFrame frame, Object type, O
434435

435436
total_align = Math.max(align, total_align);
436437

437-
setAttr.execute(frame, type, name, prop);
438+
setAttr.execute(frame, inliningTarget, type, name, prop);
438439
}
439440
stgdict.fieldsNames = fieldsNames;
440441
stgdict.fieldsOffsets = fieldsOffsets;

0 commit comments

Comments
 (0)