Skip to content

Commit 3153507

Browse files
committed
Do subclass updates for native clasess too
1 parent 8f2487d commit 3153507

File tree

2 files changed

+39
-13
lines changed

2 files changed

+39
-13
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/PythonManagedClass.java

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,16 @@
3030

3131
import com.oracle.graal.python.PythonLanguage;
3232
import com.oracle.graal.python.builtins.objects.PNone;
33+
import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject;
3334
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.PCallCapiFunction;
3435
import com.oracle.graal.python.builtins.objects.cext.capi.NativeCAPISymbol;
3536
import com.oracle.graal.python.builtins.objects.cext.capi.PythonClassNativeWrapper;
3637
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitionsFactory.PythonToNativeNodeGen;
38+
import com.oracle.graal.python.builtins.objects.common.HashingStorage;
39+
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes;
3740
import com.oracle.graal.python.builtins.objects.dict.PDict;
3841
import com.oracle.graal.python.builtins.objects.object.PythonObject;
42+
import com.oracle.graal.python.builtins.objects.referencetype.PReferenceType;
3943
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
4044
import com.oracle.graal.python.builtins.objects.type.TypeNodes.ComputeMroNode;
4145
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetSubclassesAsArrayNode;
@@ -47,6 +51,7 @@
4751
import com.oracle.graal.python.runtime.object.PFactory;
4852
import com.oracle.graal.python.runtime.sequence.storage.MroSequenceStorage;
4953
import com.oracle.truffle.api.CompilerAsserts;
54+
import com.oracle.truffle.api.CompilerDirectives;
5055
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
5156
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
5257
import com.oracle.truffle.api.nodes.Node;
@@ -209,11 +214,7 @@ public void setAttribute(TruffleString key, Object value) {
209214

210215
@TruffleBoundary
211216
public void onAttributeUpdate(TruffleString key, Object value) {
212-
for (PythonAbstractClass subclass : GetSubclassesAsArrayNode.executeUncached(this)) {
213-
if (subclass instanceof PythonManagedClass managedClass) {
214-
managedClass.onAttributeUpdate(key, value);
215-
}
216-
}
217+
callOnAttributeUpdateOnSubclasses(subClasses, key, value);
217218
methodResolutionOrder.invalidateFinalAttributeAssumption(key);
218219
if (TpSlots.canBeSpecialMethod(key, CodePointLengthNode.getUncached(), CodePointAtIndexNode.getUncached())) {
219220
if (this.tpSlots != null) {
@@ -224,6 +225,36 @@ public void onAttributeUpdate(TruffleString key, Object value) {
224225
}
225226
}
226227

228+
@TruffleBoundary
229+
public static void onAttributeUpdateNative(PythonAbstractNativeObject nativeClass, TruffleString key, Object value) {
230+
assert TypeNodes.IsTypeNode.executeUncached(nativeClass);
231+
callOnAttributeUpdateOnSubclasses(GetSubclassesNode.executeUncached(nativeClass), key, value);
232+
TypeNodes.GetMroStorageNode.executeUncached(nativeClass).invalidateFinalAttributeAssumption(key);
233+
if (TpSlots.canBeSpecialMethod(key, CodePointLengthNode.getUncached(), CodePointAtIndexNode.getUncached())) {
234+
TpSlots.updateSlot(nativeClass, key);
235+
}
236+
}
237+
238+
private static void callOnAttributeUpdateOnSubclasses(PDict subClasses, TruffleString key, Object value) {
239+
if (subClasses != null) {
240+
HashingStorage dictStorage = subClasses.getDictStorage();
241+
HashingStorageNodes.HashingStorageIterator it = HashingStorageNodes.HashingStorageGetIterator.executeUncached(dictStorage);
242+
while (HashingStorageNodes.HashingStorageIteratorNext.executeUncached(dictStorage, it)) {
243+
PReferenceType ref = (PReferenceType) HashingStorageNodes.HashingStorageIteratorValue.executeUncached(dictStorage, it);
244+
Object subclass = ref.getObject();
245+
if (subclass != null) {
246+
if (subclass instanceof PythonManagedClass managedClass) {
247+
managedClass.onAttributeUpdate(key, value);
248+
} else if (subclass instanceof PythonAbstractNativeObject nativeClass) {
249+
onAttributeUpdateNative(nativeClass, key, value);
250+
} else {
251+
throw CompilerDirectives.shouldNotReachHere("Unexpected subclass type");
252+
}
253+
}
254+
}
255+
}
256+
}
257+
227258
/**
228259
* This method supports initialization and solves boot-order problems and should not normally be
229260
* used.

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@
5757
import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass;
5858
import com.oracle.graal.python.builtins.objects.type.PythonClass;
5959
import com.oracle.graal.python.builtins.objects.type.PythonManagedClass;
60-
import com.oracle.graal.python.builtins.objects.type.TpSlots;
6160
import com.oracle.graal.python.builtins.objects.type.TypeFlags;
6261
import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsTypeNode;
6362
import com.oracle.graal.python.nodes.ErrorMessages;
@@ -239,11 +238,8 @@ static boolean writeNativeObjectOrClass(PythonAbstractNativeObject object, Truff
239238
@Cached CStructAccess.ReadObjectNode getNativeDict,
240239
@Exclusive @Cached HashingStorageSetItem setHashingStorageItem,
241240
@Exclusive @Cached InlinedBranchProfile updateStorage,
242-
@Exclusive @Cached InlinedBranchProfile canBeSpecialSlot,
243241
@Cached IsTypeNode isTypeNode,
244-
@Exclusive @Cached PRaiseNode raiseNode,
245-
@Cached TruffleString.CodePointLengthNode codePointLengthNode,
246-
@Cached TruffleString.CodePointAtIndexNode codePointAtIndexNode) {
242+
@Exclusive @Cached PRaiseNode raiseNode) {
247243
boolean isType = isTypeProfile.profile(inliningTarget, isTypeNode.execute(inliningTarget, object));
248244
try {
249245
Object dict;
@@ -269,13 +265,12 @@ static boolean writeNativeObjectOrClass(PythonAbstractNativeObject object, Truff
269265
}
270266
throw raiseNode.raise(inliningTarget, PythonBuiltinClassType.AttributeError, ErrorMessages.OBJ_P_HAS_NO_ATTR_S, object, key);
271267
} finally {
272-
if (isType && TpSlots.canBeSpecialMethod(key, codePointLengthNode, codePointAtIndexNode)) {
273-
canBeSpecialSlot.enter(inliningTarget);
268+
if (isType) {
274269
// In theory, we should do this only in type's default tp_setattr(o) slots,
275270
// one could probably bypass that by using different metaclass and
276271
// overriding tp_setattr and delegate to object's tp_setattr that does not
277272
// have this hook
278-
TpSlots.updateSlot(object, key);
273+
PythonManagedClass.onAttributeUpdateNative(object, key, value);
279274
}
280275
}
281276
}

0 commit comments

Comments
 (0)