Skip to content

Commit b84cbd6

Browse files
committed
Add array shrinking
1 parent c070147 commit b84cbd6

File tree

3 files changed

+28
-15
lines changed

3 files changed

+28
-15
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ArrayModuleBuiltins.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ PArray arrayIteratorInitializer(VirtualFrame frame, Object cls, String typeCode,
252252
}
253253
try {
254254
length = PythonUtils.addExact(length, 1);
255-
array.ensureCapacity(length);
255+
array.resizeStorage(length);
256256
} catch (OverflowException e) {
257257
CompilerDirectives.transferToInterpreterAndInvalidate();
258258
throw raise(MemoryError);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/array/ArrayBuiltins.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ Object extend(PArray self, PArray value) {
688688
try {
689689
int newLength = PythonUtils.addExact(self.getLength(), value.getLength());
690690
int itemsize = self.getFormat().bytesize;
691-
self.ensureCapacity(newLength);
691+
self.resizeStorage(newLength);
692692
PythonUtils.arraycopy(value.getBuffer(), 0, self.getBuffer(), self.getLength() * itemsize, value.getLength() * itemsize);
693693
self.setLength(newLength);
694694
return PNone.NONE;
@@ -708,7 +708,7 @@ Object extend(VirtualFrame frame, PArray self, PSequence value,
708708
int storageLength = lenNode.execute(storage);
709709
boolean capacityEnsured = false;
710710
try {
711-
self.ensureCapacity(PythonUtils.addExact(self.getLength(), storageLength));
711+
self.resizeStorage(PythonUtils.addExact(self.getLength(), storageLength));
712712
capacityEnsured = true;
713713
} catch (OverflowException e) {
714714
CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -724,7 +724,7 @@ Object extend(VirtualFrame frame, PArray self, PSequence value,
724724
} else {
725725
try {
726726
length = PythonUtils.addExact(length, 1);
727-
self.ensureCapacity(length);
727+
self.resizeStorage(length);
728728
} catch (OverflowException e) {
729729
CompilerDirectives.transferToInterpreterAndInvalidate();
730730
throw raise(MemoryError);
@@ -757,7 +757,7 @@ Object extend(VirtualFrame frame, PArray self, Object value,
757757
// in CPython
758758
try {
759759
length = PythonUtils.addExact(length, 1);
760-
self.ensureCapacity(length);
760+
self.resizeStorage(length);
761761
} catch (OverflowException e) {
762762
CompilerDirectives.transferToInterpreterAndInvalidate();
763763
throw raise(MemoryError);
@@ -936,7 +936,7 @@ Object fromlist(VirtualFrame frame, PArray self, PList list,
936936
SequenceStorage storage = getSequenceStorageNode.execute(list);
937937
int length = lenNode.execute(storage);
938938
int newLength = PythonUtils.addExact(self.getLength(), length);
939-
self.ensureCapacity(newLength);
939+
self.resizeStorage(newLength);
940940
for (int i = 0; i < length; i++) {
941941
putValueNode.execute(frame, self, self.getLength() + i, getItemScalarNode.execute(storage, i));
942942
}
@@ -988,7 +988,7 @@ Object fromunicode(VirtualFrame frame, PArray self, String str,
988988
try {
989989
int length = PString.codePointCount(str, 0, str.length());
990990
int newLength = PythonUtils.addExact(self.getLength(), length);
991-
self.ensureCapacity(newLength);
991+
self.resizeStorage(newLength);
992992
for (int i = 0, index = 0; i < length; index++) {
993993
int cpCount = PString.charCount(PString.codePointAt(str, i));
994994
String value = PString.substring(str, i, i + cpCount);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/array/PArray.java

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,26 +85,33 @@ public void setLength(int length) {
8585
}
8686

8787
private int computeNewSize(int newLength, int itemsize) throws OverflowException {
88-
// Overallocation using the same formula as CPython
89-
int newSize = ((newLength >> 4) + (length < 8 ? 3 : 7) + newLength) * itemsize;
88+
int newSize = computeNewSizeNoOverflowCheck(newLength, itemsize);
9089
if (newSize / itemsize < newLength) {
9190
throw OverflowException.INSTANCE;
9291
}
9392
return newSize;
9493
}
9594

96-
public void ensureCapacity(int newLength) throws OverflowException {
95+
private int computeNewSizeNoOverflowCheck(int newLength, int itemsize) {
96+
if (newLength == 0) {
97+
return 0;
98+
}
99+
// Overallocation using the same formula as CPython
100+
return ((newLength >> 4) + (length < 8 ? 3 : 7) + newLength) * itemsize;
101+
}
102+
103+
public void resizeStorage(int newLength) throws OverflowException {
97104
assert newLength >= 0;
98105
int itemsize = format.bytesize;
99-
if (buffer.length / itemsize < newLength) {
106+
if (buffer.length / itemsize < newLength || length + 16 >= newLength) {
100107
byte[] newBuffer = new byte[computeNewSize(newLength, itemsize)];
101-
PythonUtils.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
108+
PythonUtils.arraycopy(buffer, 0, newBuffer, 0, Math.min(buffer.length, newBuffer.length));
102109
buffer = newBuffer;
103110
}
104111
}
105112

106113
public void resize(int newLength) throws OverflowException {
107-
ensureCapacity(newLength);
114+
resizeStorage(newLength);
108115
length = newLength;
109116
}
110117

@@ -129,9 +136,15 @@ public void delSlice(int at, int count) {
129136
assert at + count <= length;
130137
int newLength = length - count;
131138
assert newLength >= 0;
132-
// TODO shrink?
133139
int itemsize = format.bytesize;
134-
PythonUtils.arraycopy(buffer, (at + count) * itemsize, buffer, at * itemsize, (length - at - count) * itemsize);
140+
if (length + 16 >= newLength) {
141+
byte[] newBuffer = new byte[computeNewSizeNoOverflowCheck(newLength, itemsize)];
142+
PythonUtils.arraycopy(buffer, 0, newBuffer, 0, at * itemsize);
143+
PythonUtils.arraycopy(buffer, (at + count) * itemsize, newBuffer, at * itemsize, (length - at - count) * itemsize);
144+
buffer = newBuffer;
145+
} else {
146+
PythonUtils.arraycopy(buffer, (at + count) * itemsize, buffer, at * itemsize, (length - at - count) * itemsize);
147+
}
135148
length = newLength;
136149
}
137150

0 commit comments

Comments
 (0)