Skip to content

Commit 41266ee

Browse files
committed
manual undo in PythonManagedClass.setSuperClass to avoid infinite cycle
1 parent 6f1490f commit 41266ee

File tree

1 file changed

+56
-17
lines changed

1 file changed

+56
-17
lines changed

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

Lines changed: 56 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import com.oracle.truffle.api.library.ExportMessage;
5656
import com.oracle.truffle.api.object.DynamicObjectLibrary;
5757
import com.oracle.truffle.api.object.Shape;
58+
import java.util.ArrayList;
5859

5960
public abstract class PythonManagedClass extends PythonObject implements PythonAbstractClass {
6061

@@ -210,31 +211,69 @@ private void unsafeSetSuperClass(PythonAbstractClass... newBaseClasses) {
210211

211212
@TruffleBoundary
212213
public void setSuperClass(PythonAbstractClass... newBaseClasses) {
213-
PythonAbstractClass[] oldBaseClasses = getBaseClasses();
214-
try {
215-
setSuperClassInternal(newBaseClasses);
216-
} catch (PException pe) {
217-
setSuperClassInternal(oldBaseClasses);
218-
throw pe;
219-
}
220-
}
221-
222-
private void setSuperClassInternal(PythonAbstractClass[] basses) {
223-
for (PythonAbstractClass base : basses) {
224-
if (base != null) {
225-
GetSubclassesNode.getUncached().execute(base).add(this);
214+
ArrayList<Set<PythonAbstractClass>> newBasesSubclasses = new ArrayList<>(newBaseClasses.length);
215+
for (int i = 0; i < newBaseClasses.length; i++) {
216+
if (newBaseClasses[i] != null) {
217+
newBasesSubclasses.add(GetSubclassesNode.getUncached().execute(newBaseClasses[i]));
226218
}
227219
}
228220

229-
this.baseClasses = basses;
230-
this.methodResolutionOrder.setInternalArrayObject(ComputeMroNode.doSlowPath(this));
221+
PythonAbstractClass[] oldBaseClasses = getBaseClasses();
222+
Object[] oldMRO = this.methodResolutionOrder.getInternalArray();
231223

232224
Set<PythonAbstractClass> subclasses = GetSubclassesNode.getUncached().execute(this);
233-
for (PythonAbstractClass scls : subclasses) {
225+
PythonAbstractClass[] subclassesArray = subclasses.toArray(new PythonAbstractClass[subclasses.size()]);
226+
Object[][] oldSubClasssMROs = new Object[subclasses.size()][];
227+
for (int i = 0; i < subclassesArray.length; i++) {
228+
PythonAbstractClass scls = subclassesArray[i];
234229
if (scls instanceof PythonManagedClass) {
235-
((PythonManagedClass) scls).methodResolutionOrder.setInternalArrayObject(ComputeMroNode.doSlowPath(scls));
230+
oldSubClasssMROs[i] = ((PythonManagedClass) scls).methodResolutionOrder.getInternalArray();
236231
}
237232
}
233+
234+
try {
235+
for (PythonAbstractClass base : newBaseClasses) {
236+
if (base != null) {
237+
GetSubclassesNode.getUncached().execute(base).add(this);
238+
}
239+
}
240+
241+
this.baseClasses = newBaseClasses;
242+
this.methodResolutionOrder.setInternalArrayObject(ComputeMroNode.doSlowPath(this));
243+
this.methodResolutionOrder.lookupChanged();
244+
245+
for (PythonAbstractClass scls : subclasses) {
246+
if (scls instanceof PythonManagedClass) {
247+
PythonManagedClass pmc = (PythonManagedClass) scls;
248+
pmc.methodResolutionOrder.setInternalArrayObject(ComputeMroNode.doSlowPath(scls));
249+
pmc.methodResolutionOrder.lookupChanged();
250+
}
251+
}
252+
} catch (PException pe) {
253+
// undo
254+
for (int i = 0; i < newBaseClasses.length; i++) {
255+
PythonAbstractClass base = newBaseClasses[i];
256+
if (base != null) {
257+
Set<PythonAbstractClass> s = GetSubclassesNode.getUncached().execute(base);
258+
s.clear();
259+
s.addAll(newBasesSubclasses.get(i));
260+
}
261+
}
262+
263+
this.baseClasses = oldBaseClasses;
264+
this.methodResolutionOrder.setInternalArrayObject(oldMRO);
265+
this.methodResolutionOrder.lookupChanged();
266+
267+
for (int i = 0; i < subclassesArray.length; i++) {
268+
PythonAbstractClass scls = subclassesArray[i];
269+
if (oldSubClasssMROs[i] != null) {
270+
PythonManagedClass pmc = (PythonManagedClass) scls;
271+
pmc.methodResolutionOrder.setInternalArrayObject(oldSubClasssMROs[i]);
272+
pmc.methodResolutionOrder.lookupChanged();
273+
}
274+
}
275+
throw pe;
276+
}
238277
}
239278

240279
final Set<PythonAbstractClass> getSubClasses() {

0 commit comments

Comments
 (0)