3030
3131import com .oracle .graal .python .PythonLanguage ;
3232import com .oracle .graal .python .builtins .objects .PNone ;
33+ import com .oracle .graal .python .builtins .objects .cext .PythonAbstractNativeObject ;
3334import com .oracle .graal .python .builtins .objects .cext .capi .CExtNodes .PCallCapiFunction ;
3435import com .oracle .graal .python .builtins .objects .cext .capi .NativeCAPISymbol ;
3536import com .oracle .graal .python .builtins .objects .cext .capi .PythonClassNativeWrapper ;
3637import 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 ;
3740import com .oracle .graal .python .builtins .objects .dict .PDict ;
3841import com .oracle .graal .python .builtins .objects .object .PythonObject ;
42+ import com .oracle .graal .python .builtins .objects .referencetype .PReferenceType ;
3943import com .oracle .graal .python .builtins .objects .tuple .PTuple ;
4044import com .oracle .graal .python .builtins .objects .type .TypeNodes .ComputeMroNode ;
4145import com .oracle .graal .python .builtins .objects .type .TypeNodes .GetSubclassesAsArrayNode ;
4751import com .oracle .graal .python .runtime .object .PFactory ;
4852import com .oracle .graal .python .runtime .sequence .storage .MroSequenceStorage ;
4953import com .oracle .truffle .api .CompilerAsserts ;
54+ import com .oracle .truffle .api .CompilerDirectives ;
5055import com .oracle .truffle .api .CompilerDirectives .CompilationFinal ;
5156import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
5257import 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.
0 commit comments