Skip to content

Commit c4b594f

Browse files
committed
[GR-9663] OutOfMemoryError is thrown when a list is extend.
PullRequest: graalpython-open/30
2 parents d859056 + 75dc645 commit c4b594f

File tree

4 files changed

+68
-15
lines changed

4 files changed

+68
-15
lines changed

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/datatype/ListTests.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ public void append() {
9494
@Test
9595
public void extend() {
9696
String source = "llist = [1,2]\n" + //
97-
"print(llist.extend([3, 4]))\n";
97+
"llist.extend([3, 4])\n" +
98+
"print(llist)\n";
9899

99100
assertPrints("[1, 2, 3, 4]\n", source);
100101
}

graalpython/com.oracle.graal.python.test/src/tests/list_tests.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -256,24 +256,24 @@ def test_append(self):
256256
self.assertEqual(a, self.type2test([0, 1, 2]))
257257

258258
self.assertRaises(TypeError, a.append)
259-
'''
259+
260260
def test_extend(self):
261261
a1 = self.type2test([0])
262262
a2 = self.type2test((0, 1))
263263
a = a1[:]
264264
a.extend(a2)
265265
self.assertEqual(a, a1 + a2)
266-
266+
267267
a.extend(self.type2test([]))
268268
self.assertEqual(a, a1 + a2)
269-
269+
270270
a.extend(a)
271271
self.assertEqual(a, self.type2test([0, 0, 1, 0, 0, 1]))
272-
272+
273273
a = self.type2test("spam")
274274
a.extend("eggs")
275275
self.assertEqual(a, list("spameggs"))
276-
276+
277277
self.assertRaises(TypeError, a.extend, None)
278278
self.assertRaises(TypeError, a.extend)
279279

@@ -288,7 +288,7 @@ def __length_hint__(self):
288288
a = self.type2test([1,2,3,4])
289289
a.extend(CustomIter())
290290
self.assertEqual(a, [1,2,3,4])
291-
'''
291+
292292
def test_insert(self):
293293
a = self.type2test([0, 1, 2])
294294
a.insert(0, -2)

graalpython/com.oracle.graal.python.test/src/tests/test_list.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -280,13 +280,32 @@ def test_set_slice_generalize_storage(self):
280280
a[1:5] = [1.1, 2.2, 3.3]
281281
self.assertEqual([1,1.1, 2.2, 3.3], a)
282282

283+
def test_extend_spec(self):
284+
a = [1,2]
285+
a.extend(a)
286+
self.assertEqual([1,2,1,2], a)
287+
a = [923123123123]
288+
a.extend(a)
289+
self.assertEqual([923123123123,923123123123], a)
290+
a = [1.1, 2.1]
291+
a.extend(a)
292+
self.assertEqual([1.1, 2.1, 1.1, 2.1], a)
293+
294+
a = []
295+
a.extend(range(1,4))
296+
self.assertEqual([1,2,3], a)
297+
298+
a = []
299+
a.extend('ahoj')
300+
self.assertEqual(['a','h','o','j'], a)
301+
283302
def test_remove_spec(self):
284303
a = [1,2]
285304
a.remove(2);
286305
self.assertEqual([1], a)
287306
a.remove(1)
288307
self.assertEqual([], a)
289-
308+
290309
a = [0,1,0,1,2]
291310
a.remove(True)
292311
self.assertEqual([0,0,1,2], a)
@@ -296,10 +315,10 @@ def test_remove_spec(self):
296315
a = list([LONG_NUMBER, LONG_NUMBER + 1])
297316
a.remove(LONG_NUMBER + 1)
298317
self.assertEqual([LONG_NUMBER], a)
299-
318+
300319
class MyInt(int):
301320
pass
302-
321+
303322
a = [1,2,3]
304323
a.remove(MyInt(2))
305324
self.assertEqual([1,3], a)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/list/ListBuiltins.java

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import com.oracle.graal.python.builtins.objects.iterator.PIntegerSequenceIterator;
5959
import com.oracle.graal.python.builtins.objects.iterator.PLongSequenceIterator;
6060
import com.oracle.graal.python.builtins.objects.iterator.PSequenceIterator;
61+
import com.oracle.graal.python.builtins.objects.range.PRange;
6162
import com.oracle.graal.python.builtins.objects.slice.PSlice;
6263
import com.oracle.graal.python.builtins.objects.str.PString;
6364
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
@@ -486,24 +487,56 @@ protected boolean isKnownStorage(PList list) {
486487
@GenerateNodeFactory
487488
public abstract static class ListExtendNode extends PythonBuiltinNode {
488489

489-
@Specialization
490-
public PList extend(PList list, Object source,
490+
@Specialization(guards = {"isPSequenceWithStorage(source)"}, rewriteOn = {SequenceStoreException.class})
491+
public PNone extendSequenceStore(PList list, Object source) throws SequenceStoreException {
492+
SequenceStorage target = list.getSequenceStorage();
493+
target.extend(((PSequence) source).getSequenceStorage());
494+
return PNone.NONE;
495+
}
496+
497+
@Specialization(guards = {"isPSequenceWithStorage(source)"})
498+
public PNone extendSequence(PList list, Object source) {
499+
SequenceStorage eSource = ((PSequence) source).getSequenceStorage();
500+
if (eSource.length() > 0) {
501+
SequenceStorage target = list.getSequenceStorage();
502+
try {
503+
target.extend(eSource);
504+
} catch (SequenceStoreException e) {
505+
target = target.generalizeFor(eSource.getItemNormalized(0));
506+
list.setSequenceStorage(target);
507+
try {
508+
target.extend(eSource);
509+
} catch (SequenceStoreException e1) {
510+
throw new IllegalStateException();
511+
}
512+
}
513+
}
514+
return PNone.NONE;
515+
}
516+
517+
@Specialization(guards = "!isPSequenceWithStorage(source)")
518+
public PNone extend(PList list, Object source,
491519
@Cached("create()") GetIteratorNode getIterator,
492520
@Cached("create()") GetNextNode next,
493521
@Cached("createBinaryProfile()") ConditionProfile errorProfile) {
494-
495-
Object iterator = getIterator.executeWith(source);
522+
Object workSource = list != source ? source : factory().createList(((PList) source).getSequenceStorage().copy());
523+
Object iterator = getIterator.executeWith(workSource);
496524
while (true) {
497525
Object value;
498526
try {
499527
value = next.execute(iterator);
500528
} catch (PException e) {
501529
e.expectStopIteration(getCore(), errorProfile);
502-
return list;
530+
return PNone.NONE;
503531
}
504532
list.append(value);
505533
}
506534
}
535+
536+
protected boolean isPSequenceWithStorage(Object source) {
537+
return (source instanceof PSequence && !(source instanceof PTuple || source instanceof PRange));
538+
}
539+
507540
}
508541

509542
// list.insert(i, x)

0 commit comments

Comments
 (0)