97
97
import com .oracle .graal .python .runtime .exception .PException ;
98
98
import com .oracle .graal .python .runtime .exception .PythonErrorType ;
99
99
import com .oracle .graal .python .runtime .exception .PythonExitException ;
100
+ import com .oracle .graal .python .runtime .sequence .storage .ByteSequenceStorage ;
100
101
import com .oracle .truffle .api .CompilerDirectives ;
101
102
import com .oracle .truffle .api .CompilerDirectives .CompilationFinal ;
102
103
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
@@ -548,11 +549,15 @@ int dup(int fd) {
548
549
return getResources ().dup (fd );
549
550
}
550
551
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 ) {
554
559
try {
555
- return getResources (). dup ( fd . intValueExact () );
560
+ return dupPInt ( fd );
556
561
} catch (ArithmeticException e ) {
557
562
throw raise (OSError , "invalid fd %r" , fd );
558
563
}
@@ -663,11 +668,6 @@ Object close(int fd,
663
668
throw raise (OSError , "invalid fd" );
664
669
} else {
665
670
resources .close (fd );
666
- try {
667
- channel .close ();
668
- } catch (IOException e ) {
669
- throw raise (OSError , e .getMessage ());
670
- }
671
671
}
672
672
return PNone .NONE ;
673
673
}
@@ -789,12 +789,15 @@ public static WriteNode create() {
789
789
@ GenerateNodeFactory
790
790
@ TypeSystemReference (PythonArithmeticTypes .class )
791
791
public abstract static class ReadNode extends PythonFileNode {
792
+ private static final int MAX_READ = Integer .MAX_VALUE / 2 ;
793
+
792
794
@ Specialization (guards = "readOpaque(frame)" )
793
795
Object readOpaque (@ SuppressWarnings ("unused" ) VirtualFrame frame , int fd , @ SuppressWarnings ("unused" ) Object requestedSize ,
794
796
@ Cached ("createClassProfile()" ) ValueProfile channelClassProfile ) {
795
797
Channel channel = getResources ().getFileChannel (fd , channelClassProfile );
796
798
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 ()));
798
801
} catch (IOException e ) {
799
802
throw raise (OSError , e .getMessage ());
800
803
}
@@ -805,46 +808,41 @@ Object read(@SuppressWarnings("unused") VirtualFrame frame, int fd, long request
805
808
@ Cached ("createClassProfile()" ) ValueProfile channelClassProfile ) {
806
809
Channel channel = getResources ().getFileChannel (fd , channelClassProfile );
807
810
try {
808
- byte [] array = doRead (channel , (int ) requestedSize );
811
+ ByteSequenceStorage array = doRead (channel , (int ) requestedSize );
809
812
return factory ().createBytes (array );
810
813
} catch (IOException e ) {
811
814
throw raise (OSError , e .getMessage ());
812
815
}
813
816
}
814
817
815
- @ TruffleBoundary
816
- private byte [] doRead (Channel channel , int requestedSize ) throws IOException {
818
+ private ByteSequenceStorage doRead (Channel channel , int requestedSize ) throws IOException {
817
819
if (channel instanceof ReadableByteChannel ) {
818
820
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 );
836
826
} else {
837
827
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 ;
843
831
}
844
832
}
845
833
throw raise (OSError , "file not opened for reading" );
846
834
}
847
835
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
+
848
846
/**
849
847
* @param frame - only used so the DSL sees this as a dynamic check
850
848
*/
0 commit comments