Skip to content

Commit 7121878

Browse files
committed
try to avoid copying the backing buffer in a read
1 parent a6f11f1 commit 7121878

File tree

3 files changed

+37
-38
lines changed

3 files changed

+37
-38
lines changed

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

Lines changed: 33 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@
9797
import com.oracle.graal.python.runtime.exception.PException;
9898
import com.oracle.graal.python.runtime.exception.PythonErrorType;
9999
import com.oracle.graal.python.runtime.exception.PythonExitException;
100+
import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage;
100101
import com.oracle.truffle.api.CompilerDirectives;
101102
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
102103
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -548,11 +549,15 @@ int dup(int fd) {
548549
return getResources().dup(fd);
549550
}
550551

551-
@Specialization
552-
@TruffleBoundary
553-
int dup(PInt fd) {
552+
@Specialization(rewriteOn = ArithmeticException.class)
553+
int dupPInt(PInt fd) {
554+
return getResources().dup(fd.intValueExact());
555+
}
556+
557+
@Specialization(replaces = "dupPInt")
558+
int dupOvf(PInt fd) {
554559
try {
555-
return getResources().dup(fd.intValueExact());
560+
return dupPInt(fd);
556561
} catch (ArithmeticException e) {
557562
throw raise(OSError, "invalid fd %r", fd);
558563
}
@@ -663,11 +668,6 @@ Object close(int fd,
663668
throw raise(OSError, "invalid fd");
664669
} else {
665670
resources.close(fd);
666-
try {
667-
channel.close();
668-
} catch (IOException e) {
669-
throw raise(OSError, e.getMessage());
670-
}
671671
}
672672
return PNone.NONE;
673673
}
@@ -789,12 +789,15 @@ public static WriteNode create() {
789789
@GenerateNodeFactory
790790
@TypeSystemReference(PythonArithmeticTypes.class)
791791
public abstract static class ReadNode extends PythonFileNode {
792+
private static final int MAX_READ = Integer.MAX_VALUE / 2;
793+
792794
@Specialization(guards = "readOpaque(frame)")
793795
Object readOpaque(@SuppressWarnings("unused") VirtualFrame frame, int fd, @SuppressWarnings("unused") Object requestedSize,
794796
@Cached("createClassProfile()") ValueProfile channelClassProfile) {
795797
Channel channel = getResources().getFileChannel(fd, channelClassProfile);
796798
try {
797-
return new OpaqueBytes(doRead(channel, Integer.MAX_VALUE));
799+
ByteSequenceStorage bytes = doRead(channel, MAX_READ);
800+
return new OpaqueBytes(Arrays.copyOf(bytes.getInternalByteArray(), bytes.length()));
798801
} catch (IOException e) {
799802
throw raise(OSError, e.getMessage());
800803
}
@@ -805,46 +808,41 @@ Object read(@SuppressWarnings("unused") VirtualFrame frame, int fd, long request
805808
@Cached("createClassProfile()") ValueProfile channelClassProfile) {
806809
Channel channel = getResources().getFileChannel(fd, channelClassProfile);
807810
try {
808-
byte[] array = doRead(channel, (int) requestedSize);
811+
ByteSequenceStorage array = doRead(channel, (int) requestedSize);
809812
return factory().createBytes(array);
810813
} catch (IOException e) {
811814
throw raise(OSError, e.getMessage());
812815
}
813816
}
814817

815-
@TruffleBoundary
816-
private byte[] doRead(Channel channel, int requestedSize) throws IOException {
818+
private ByteSequenceStorage doRead(Channel channel, int requestedSize) throws IOException {
817819
if (channel instanceof ReadableByteChannel) {
818820
ReadableByteChannel readableChannel = (ReadableByteChannel) channel;
819-
int sz;
820-
if (requestedSize > (Integer.MAX_VALUE / 2)) {
821-
// common VM limit
822-
sz = Integer.MAX_VALUE / 2;
823-
} else {
824-
sz = requestedSize;
825-
}
826-
ByteBuffer dst;
827-
try {
828-
dst = ByteBuffer.allocate(sz);
829-
} catch (OutOfMemoryError e) {
830-
// we just read less, that's allowed
831-
dst = ByteBuffer.allocate(8192);
832-
}
833-
int readSize = readableChannel.read(dst);
834-
if (readSize == -1) {
835-
return new byte[0];
821+
int sz = Math.min(requestedSize, MAX_READ);
822+
ByteBuffer dst = allocateBuffer(sz);
823+
int readSize = readIntoBuffer(readableChannel, dst);
824+
if (readSize <= 0) {
825+
return new ByteSequenceStorage(0);
836826
} else {
837827
byte[] array = dst.array();
838-
if (array.length != readSize) {
839-
return Arrays.copyOf(array, readSize);
840-
} else {
841-
return array;
842-
}
828+
ByteSequenceStorage byteSequenceStorage = new ByteSequenceStorage(array);
829+
byteSequenceStorage.setNewLength(readSize);
830+
return byteSequenceStorage;
843831
}
844832
}
845833
throw raise(OSError, "file not opened for reading");
846834
}
847835

836+
@TruffleBoundary
837+
private static int readIntoBuffer(ReadableByteChannel readableChannel, ByteBuffer dst) throws IOException {
838+
return readableChannel.read(dst);
839+
}
840+
841+
@TruffleBoundary
842+
private static ByteBuffer allocateBuffer(int sz) {
843+
return ByteBuffer.allocate(sz);
844+
}
845+
848846
/**
849847
* @param frame - only used so the DSL sees this as a dynamic check
850848
*/

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/BytesBuiltins.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
6969
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
7070
import com.oracle.graal.python.runtime.exception.PythonErrorType;
71+
import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage;
7172
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
7273
import com.oracle.truffle.api.CompilerDirectives;
7374
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -245,7 +246,7 @@ public abstract static class AddNode extends PythonBinaryBuiltinNode {
245246
@Specialization
246247
public Object add(PBytes left, PIBytesLike right,
247248
@Cached("create()") SequenceStorageNodes.ConcatNode concatNode) {
248-
SequenceStorage res = concatNode.execute(left.getSequenceStorage(), right.getSequenceStorage());
249+
ByteSequenceStorage res = (ByteSequenceStorage) concatNode.execute(left.getSequenceStorage(), right.getSequenceStorage());
249250
return factory().createBytes(res);
250251
}
251252

@@ -262,7 +263,7 @@ public abstract static class MulNode extends PythonBinaryBuiltinNode {
262263
@Specialization
263264
public Object mul(PBytes self, int times,
264265
@Cached("create()") SequenceStorageNodes.RepeatNode repeatNode) {
265-
SequenceStorage res = repeatNode.execute(self.getSequenceStorage(), times);
266+
ByteSequenceStorage res = (ByteSequenceStorage) repeatNode.execute(self.getSequenceStorage(), times);
266267
return factory().createBytes(res);
267268
}
268269

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ public PBytes createBytes(LazyPythonClass cls, byte[] array) {
275275
return trace(new PBytes(cls, array));
276276
}
277277

278-
public PBytes createBytes(SequenceStorage storage) {
278+
public PBytes createBytes(ByteSequenceStorage storage) {
279279
return trace(new PBytes(PythonBuiltinClassType.PBytes, storage));
280280
}
281281

0 commit comments

Comments
 (0)