Skip to content

Commit c49d287

Browse files
committed
[GR-9663] OutOfMemoryError is thrown when a list is extend.
1 parent b07c135 commit c49d287

File tree

3 files changed

+92
-10
lines changed

3 files changed

+92
-10
lines changed

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: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,16 @@ 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)
283293
def test_remove_spec(self):
284294
a = [1,2]
285295
a.remove(2);

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

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -477,24 +477,96 @@ protected boolean isKnownStorage(PList list) {
477477
@GenerateNodeFactory
478478
public abstract static class ListExtendNode extends PythonBuiltinNode {
479479

480-
@Specialization
481-
public PList extend(PList list, Object source,
480+
@Specialization(guards = {"isIntStorage(list)", "isIntStorage(source)"})
481+
public PNone extendIntInt(PList list, PList source) {
482+
IntSequenceStorage target = (IntSequenceStorage) list.getSequenceStorage();
483+
IntSequenceStorage what = list != source
484+
? (IntSequenceStorage) source.getSequenceStorage()
485+
: (IntSequenceStorage) source.getSequenceStorage().copy();
486+
int[] array = what.getInternalIntArray();
487+
for (int i = 0; i < what.length(); i++) {
488+
target.appendInt(array[i]);
489+
}
490+
return PNone.NONE;
491+
}
492+
493+
@Specialization(guards = {"isLongStorage(list)", "isIntStorage(source)"})
494+
public PNone extendLongInt(PList list, PList source) {
495+
LongSequenceStorage target = (LongSequenceStorage) list.getSequenceStorage();
496+
IntSequenceStorage what = list != source
497+
? (IntSequenceStorage) source.getSequenceStorage()
498+
: (IntSequenceStorage) source.getSequenceStorage().copy();
499+
int[] array = what.getInternalIntArray();
500+
for (int i = 0; i < what.length(); i++) {
501+
target.appendLong(array[i]);
502+
}
503+
return PNone.NONE;
504+
}
505+
506+
@Specialization(guards = {"isLongStorage(list)", "isLongStorage(source)"})
507+
public PNone extendLongLong(PList list, PList source) {
508+
LongSequenceStorage target = (LongSequenceStorage) list.getSequenceStorage();
509+
LongSequenceStorage what = list != source
510+
? (LongSequenceStorage) source.getSequenceStorage()
511+
: (LongSequenceStorage) source.getSequenceStorage().copy();
512+
long[] array = what.getInternalLongArray();
513+
for (int i = 0; i < what.length(); i++) {
514+
target.appendLong(array[i]);
515+
}
516+
return PNone.NONE;
517+
}
518+
519+
@Specialization(guards = {"isDoubleStorage(list)", "isDoubleStorage(source)"})
520+
public PNone extendDoubleDouble(PList list, PList source) {
521+
DoubleSequenceStorage target = (DoubleSequenceStorage) list.getSequenceStorage();
522+
DoubleSequenceStorage what = list != source
523+
? (DoubleSequenceStorage) source.getSequenceStorage()
524+
: (DoubleSequenceStorage) source.getSequenceStorage().copy();
525+
double[] array = what.getInternalDoubleArray();
526+
for (int i = 0; i < what.length(); i++) {
527+
target.appendDouble(array[i]);
528+
}
529+
return PNone.NONE;
530+
}
531+
532+
@Specialization(guards = {"isObjectStorage(list)", "isObjectStorage(source)"})
533+
public PNone extendObjectObject(PList list, PList source) {
534+
ObjectSequenceStorage target = (ObjectSequenceStorage) list.getSequenceStorage();
535+
ObjectSequenceStorage what = list != source
536+
? (ObjectSequenceStorage) source.getSequenceStorage()
537+
: (ObjectSequenceStorage) source.getSequenceStorage().copy();
538+
Object[] array = what.getInternalArray();
539+
for (int i = 0; i < what.length(); i++) {
540+
target.append(array[i]);
541+
}
542+
return PNone.NONE;
543+
}
544+
545+
@Specialization(guards = "isNotSpecialCase(list, source)")
546+
public PNone extend(PList list, Object source,
482547
@Cached("create()") GetIteratorNode getIterator,
483548
@Cached("create()") GetNextNode next,
484549
@Cached("createBinaryProfile()") ConditionProfile errorProfile) {
485550

486-
Object iterator = getIterator.executeWith(source);
551+
Object workSource = list != source ? source : factory().createList(((PList) source).getSequenceStorage().copy());
552+
Object iterator = getIterator.executeWith(workSource);
487553
while (true) {
488554
Object value;
489555
try {
490556
value = next.execute(iterator);
491557
} catch (PException e) {
492558
e.expectStopIteration(getCore(), errorProfile);
493-
return list;
559+
return PNone.NONE;
494560
}
495561
list.append(value);
496562
}
497563
}
564+
565+
protected boolean isNotSpecialCase(PList list, Object source) {
566+
return !(source instanceof PList && (((PGuards.isIntStorage(list) || PGuards.isLongStorage(list)) && PGuards.isIntStorage((PList) source)) ||
567+
(PGuards.isLongStorage(list) && PGuards.isLongStorage((PList) source)) || (PGuards.isDoubleStorage(list) && PGuards.isDoubleStorage((PList) source)) ||
568+
(PGuards.isObjectStorage(list) && PGuards.isObjectStorage((PList) source))));
569+
}
498570
}
499571

500572
// list.insert(i, x)

0 commit comments

Comments
 (0)