Skip to content

Commit e0303f3

Browse files
committed
Fix: use rotate to implement remove
1 parent 6b59d12 commit e0303f3

File tree

2 files changed

+32
-11
lines changed

2 files changed

+32
-11
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/deque/DequeBuiltins.java

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@
6565
import static com.oracle.graal.python.nodes.SpecialMethodNames.__RMUL__;
6666
import static com.oracle.graal.python.nodes.SpecialMethodNames.__SETITEM__;
6767

68-
import java.util.ConcurrentModificationException;
6968
import java.util.Iterator;
7069
import java.util.List;
7170

@@ -467,20 +466,34 @@ public abstract static class DequeRemoveNode extends PythonBinaryBuiltinNode {
467466

468467
@Specialization
469468
@TruffleBoundary
470-
Object doGeneric(PDeque self, Object value) {
469+
Object doGeneric(PDeque self, Object value,
470+
@CachedLibrary(limit = "3") PythonObjectLibrary itemLib) {
471471
PythonObjectLibrary valueLib = PythonObjectLibrary.getFactory().getUncached(value);
472-
PythonObjectLibrary itemLib = PythonObjectLibrary.getUncached();
473-
Iterator<Object> iterator = self.data.iterator();
474-
try {
475-
while (iterator.hasNext()) {
476-
Object item = iterator.next();
477-
if (itemLib.equals(item, value, valueLib)) {
478-
iterator.remove();
472+
// CPython captures the size before iteration
473+
int n = self.getSize();
474+
for (int i = 0; i < n; i++) {
475+
try {
476+
boolean result = itemLib.equals(self.peekLeft(), value, valueLib);
477+
if (n != self.getSize()) {
478+
throw PRaiseNode.raiseUncached(this, IndexError, "deque mutated during remove().");
479+
}
480+
if (result) {
481+
Object removed = self.popLeft();
482+
assert removed != null;
483+
DequeRotateNode.doRight(self, i);
479484
return PNone.NONE;
485+
} else {
486+
// this is basically 'DequeRotateNode.doLeft(self, -1)'
487+
self.append(self.popLeft());
480488
}
489+
} catch (PException e) {
490+
/*
491+
* In case of an error during comparison, we need to restore the original deque
492+
* by rotating.
493+
*/
494+
DequeRotateNode.doRight(self, i);
495+
throw e;
481496
}
482-
} catch (ConcurrentModificationException e) {
483-
throw PRaiseNode.raiseUncached(this, IndexError, "deque mutated during remove().");
484497
}
485498
throw PRaiseNode.raiseUncached(this, ValueError, "deque.remove(x): x not in deque");
486499
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/deque/PDeque.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,14 @@ Object popLeft() {
128128
return data.pollFirst();
129129
}
130130

131+
/**
132+
* Returns {@code null} if empty.
133+
*/
134+
@TruffleBoundary
135+
Object peekLeft() {
136+
return data.peekFirst();
137+
}
138+
131139
@TruffleBoundary
132140
void addAll(Object[] c) {
133141
for (Object e : c) {

0 commit comments

Comments
 (0)