59
59
60
60
import java .io .IOException ;
61
61
import java .nio .ByteBuffer ;
62
+ import java .nio .channels .Channel ;
62
63
import java .nio .channels .SeekableByteChannel ;
63
64
import java .util .List ;
64
65
69
70
import com .oracle .graal .python .builtins .objects .PNone ;
70
71
import com .oracle .graal .python .builtins .objects .bytes .PBytes ;
71
72
import com .oracle .graal .python .builtins .objects .bytes .PIBytesLike ;
73
+ import com .oracle .graal .python .builtins .objects .common .SequenceNodes ;
72
74
import com .oracle .graal .python .builtins .objects .common .SequenceStorageNodes ;
73
75
import com .oracle .graal .python .builtins .objects .common .SequenceStorageNodes .NoGeneralizationNode ;
74
76
import com .oracle .graal .python .builtins .objects .common .SequenceStorageNodes .NormalizeIndexNode ;
83
85
import com .oracle .graal .python .nodes .function .PythonBuiltinBaseNode ;
84
86
import com .oracle .graal .python .nodes .function .PythonBuiltinNode ;
85
87
import com .oracle .graal .python .nodes .function .builtins .PythonBinaryBuiltinNode ;
86
- import com .oracle .graal .python .nodes .function .builtins .PythonTernaryBuiltinNode ;
87
88
import com .oracle .graal .python .nodes .function .builtins .PythonUnaryBuiltinNode ;
88
89
import com .oracle .graal .python .nodes .truffle .PythonArithmeticTypes ;
89
90
import com .oracle .graal .python .nodes .util .CastToByteNode ;
90
91
import com .oracle .graal .python .nodes .util .CastToIndexNode ;
91
92
import com .oracle .graal .python .nodes .util .CastToJavaLongNode ;
93
+ import com .oracle .graal .python .nodes .util .ChannelNodes ;
92
94
import com .oracle .graal .python .nodes .util .ChannelNodes .ReadByteFromChannelNode ;
93
95
import com .oracle .graal .python .nodes .util .ChannelNodes .ReadFromChannelNode ;
96
+ import com .oracle .graal .python .nodes .util .ChannelNodes .WriteByteToChannelNode ;
97
+ import com .oracle .graal .python .nodes .util .ChannelNodes .WriteToChannelNode ;
94
98
import com .oracle .graal .python .runtime .sequence .storage .ByteSequenceStorage ;
95
99
import com .oracle .graal .python .runtime .sequence .storage .SequenceStorage ;
96
100
import com .oracle .truffle .api .CompilerDirectives ;
102
106
import com .oracle .truffle .api .dsl .TypeSystemReference ;
103
107
import com .oracle .truffle .api .frame .VirtualFrame ;
104
108
import com .oracle .truffle .api .profiles .BranchProfile ;
109
+ import com .oracle .truffle .api .profiles .ConditionProfile ;
105
110
106
111
@ CoreFunctions (extendClasses = PythonBuiltinClassType .PMMap )
107
112
public class MMapBuiltins extends PythonBuiltins {
108
113
114
+ protected interface ByteReadingNode {
115
+
116
+ static ReadByteFromChannelNode createValueError () {
117
+ return ReadByteFromChannelNode .create (() -> new ChannelNodes .ReadByteErrorHandler () {
118
+
119
+ @ Override
120
+ public int execute (Channel channel ) {
121
+ throw raise (PythonBuiltinClassType .ValueError , "read byte out of range" );
122
+ }
123
+ });
124
+ }
125
+
126
+ static ReadByteFromChannelNode createIndexError () {
127
+ return ReadByteFromChannelNode .create (() -> new ChannelNodes .ReadByteErrorHandler () {
128
+
129
+ @ Override
130
+ public int execute (Channel channel ) {
131
+ throw raise (PythonBuiltinClassType .IndexError , "mmap index out of range" );
132
+ }
133
+ });
134
+
135
+ }
136
+ }
137
+
138
+ protected interface ByteWritingNode {
139
+
140
+ static WriteByteToChannelNode createValueError () {
141
+ return WriteByteToChannelNode .create (() -> new ChannelNodes .WriteByteErrorHandler () {
142
+
143
+ @ Override
144
+ public void execute (Channel channel , byte b ) {
145
+ throw raise (PythonBuiltinClassType .ValueError , "write byte out of range" );
146
+ }
147
+ });
148
+ }
149
+
150
+ static WriteByteToChannelNode createIndexError () {
151
+ return WriteByteToChannelNode .create (() -> new ChannelNodes .WriteByteErrorHandler () {
152
+
153
+ @ Override
154
+ public void execute (Channel channel , byte b ) {
155
+ throw raise (PythonBuiltinClassType .IndexError , "mmap index out of range" );
156
+ }
157
+ });
158
+
159
+ }
160
+ }
161
+
109
162
@ Override
110
163
protected List <? extends NodeFactory <? extends PythonBuiltinBaseNode >> getNodeFactories () {
111
164
return MMapBuiltinsFactory .getFactories ();
@@ -173,11 +226,11 @@ abstract static class ReprNode extends StrNode {
173
226
174
227
@ Builtin (name = __GETITEM__ , fixedNumOfPositionalArgs = 2 )
175
228
@ GenerateNodeFactory
176
- abstract static class GetItemNode extends PythonBuiltinNode {
229
+ abstract static class GetItemNode extends PythonBuiltinNode implements ByteReadingNode {
177
230
178
231
@ Specialization (guards = "!isPSlice(idxObj)" )
179
232
int doSingle (VirtualFrame frame , PMMap self , Object idxObj ,
180
- @ Cached ("create ()" ) ReadByteFromChannelNode readByteNode ,
233
+ @ Cached ("createIndexError ()" ) ReadByteFromChannelNode readByteNode ,
181
234
@ Cached ("createExact()" ) CastToJavaLongNode castToLongNode ,
182
235
@ Cached ("create()" ) InternalLenNode lenNode ) {
183
236
@@ -226,12 +279,82 @@ Object doSlice(VirtualFrame frame, PMMap self, PSlice idx,
226
279
throw raise (PythonBuiltinClassType .OSError , e .getMessage ());
227
280
}
228
281
}
282
+
229
283
}
230
284
231
285
@ Builtin (name = SpecialMethodNames .__SETITEM__ , fixedNumOfPositionalArgs = 3 )
232
286
@ GenerateNodeFactory
233
- abstract static class SetItemNode extends PythonTernaryBuiltinNode {
287
+ abstract static class SetItemNode extends PythonBuiltinNode implements ByteWritingNode {
288
+
289
+ @ Specialization (guards = "!isPSlice(idxObj)" )
290
+ PNone doSingle (VirtualFrame frame , PMMap self , Object idxObj , Object val ,
291
+ @ Cached ("createIndexError()" ) WriteByteToChannelNode writeByteNode ,
292
+ @ Cached ("createExact()" ) CastToJavaLongNode castToLongNode ,
293
+ @ Cached ("createCoerce()" ) CastToByteNode castToByteNode ,
294
+ @ Cached ("create()" ) InternalLenNode lenNode ,
295
+ @ Cached ("createBinaryProfile()" ) ConditionProfile outOfRangeProfile ) {
296
+
297
+ try {
298
+ long i = castToLongNode .execute (idxObj );
299
+ long len = lenNode .execute (frame , self );
300
+ SeekableByteChannel channel = self .getChannel ();
301
+ long idx = i < 0 ? i + len : i ;
302
+
303
+ if (outOfRangeProfile .profile (idx < 0 || idx >= len )) {
304
+ throw raise (PythonBuiltinClassType .IndexError , "mmap index out of range" );
305
+ }
306
+
307
+ // save current position
308
+ long oldPos = channel .position ();
234
309
310
+ channel .position (idx );
311
+ writeByteNode .execute (channel , castToByteNode .execute (val ));
312
+
313
+ // restore position
314
+ channel .position (oldPos );
315
+
316
+ return PNone .NONE ;
317
+
318
+ } catch (IOException e ) {
319
+ throw raise (PythonBuiltinClassType .OSError , e .getMessage ());
320
+ }
321
+ }
322
+
323
+ @ Specialization
324
+ PNone doSlice (VirtualFrame frame , PMMap self , PSlice idx , PIBytesLike val ,
325
+ @ Cached ("create()" ) WriteToChannelNode writeNode ,
326
+ @ Cached ("create()" ) SequenceNodes .GetSequenceStorageNode getStorageNode ,
327
+ @ Cached ("create()" ) InternalLenNode lenNode ,
328
+ @ Cached ("createBinaryProfile()" ) ConditionProfile invalidStepProfile ) {
329
+
330
+ try {
331
+ long len = lenNode .execute (frame , self );
332
+ SliceInfo info = idx .computeIndices (PInt .intValueExact (len ));
333
+ SeekableByteChannel channel = self .getChannel ();
334
+
335
+ if (invalidStepProfile .profile (info .step != 1 )) {
336
+ throw raise (PythonBuiltinClassType .SystemError , "step != 1 not supported" );
337
+ }
338
+
339
+ // save current position
340
+ long oldPos = channel .position ();
341
+
342
+ channel .position (info .start );
343
+ writeNode .execute (channel , getStorageNode .execute (val ), info .length );
344
+
345
+ // restore position
346
+ channel .position (oldPos );
347
+
348
+ return PNone .NONE ;
349
+
350
+ } catch (IOException e ) {
351
+ throw raise (PythonBuiltinClassType .OSError , e .getMessage ());
352
+ }
353
+ }
354
+
355
+ protected static CastToByteNode createCoerce () {
356
+ return CastToByteNode .create (true );
357
+ }
235
358
}
236
359
237
360
@ Builtin (name = __LEN__ , fixedNumOfPositionalArgs = 1 )
@@ -280,6 +403,16 @@ PNone close(PMMap self) {
280
403
}
281
404
}
282
405
406
+ @ Builtin (name = "closed" , fixedNumOfPositionalArgs = 1 , isGetter = true )
407
+ @ GenerateNodeFactory
408
+ abstract static class ClosedNode extends PythonUnaryBuiltinNode {
409
+
410
+ @ Specialization
411
+ boolean close (PMMap self ) {
412
+ return !self .getChannel ().isOpen ();
413
+ }
414
+ }
415
+
283
416
@ Builtin (name = "size" , fixedNumOfPositionalArgs = 1 )
284
417
@ GenerateNodeFactory
285
418
abstract static class SizeNode extends PythonBuiltinNode {
@@ -309,11 +442,11 @@ long readline(VirtualFrame frame, PMMap self) {
309
442
@ Builtin (name = "read_byte" , fixedNumOfPositionalArgs = 1 )
310
443
@ GenerateNodeFactory
311
444
@ TypeSystemReference (PythonArithmeticTypes .class )
312
- abstract static class ReadByteNode extends PythonUnaryBuiltinNode {
445
+ abstract static class ReadByteNode extends PythonUnaryBuiltinNode implements ByteReadingNode {
313
446
314
447
@ Specialization
315
448
int readByte (PMMap self ,
316
- @ Cached ("create ()" ) ReadByteFromChannelNode readByteNode ) {
449
+ @ Cached ("createValueError ()" ) ReadByteFromChannelNode readByteNode ) {
317
450
return readByteNode .execute (self .getChannel ());
318
451
}
319
452
}
@@ -337,6 +470,7 @@ PBytes read(PMMap self, Object n,
337
470
ByteSequenceStorage res = readChannelNode .execute (self .getChannel (), castToIndexNode .execute (n ));
338
471
return factory ().createBytes (res );
339
472
}
473
+
340
474
}
341
475
342
476
@ Builtin (name = "readline" , fixedNumOfPositionalArgs = 1 )
@@ -433,7 +567,7 @@ private Object doSeek(PMMap self, long dist, int how) throws IOException {
433
567
@ Builtin (name = "find" , minNumOfPositionalArgs = 2 , maxNumOfPositionalArgs = 4 )
434
568
@ GenerateNodeFactory
435
569
@ TypeSystemReference (PythonArithmeticTypes .class )
436
- public abstract static class FindNode extends PythonBuiltinNode {
570
+ public abstract static class FindNode extends PythonBuiltinNode implements ByteReadingNode {
437
571
438
572
@ Child private NormalizeIndexNode normalizeIndexNode ;
439
573
@ Child private SequenceStorageNodes .GetItemNode getLeftItemNode ;
@@ -443,7 +577,7 @@ public abstract static class FindNode extends PythonBuiltinNode {
443
577
444
578
@ Specialization
445
579
long find (PMMap primary , PIBytesLike sub , Object starting , Object ending ,
446
- @ Cached ("create ()" ) ReadByteFromChannelNode readByteNode ) {
580
+ @ Cached ("createValueError ()" ) ReadByteFromChannelNode readByteNode ) {
447
581
try {
448
582
SeekableByteChannel channel = primary .getChannel ();
449
583
long len1 = channel .size ();
@@ -484,7 +618,7 @@ long find(PMMap primary, PIBytesLike sub, Object starting, Object ending,
484
618
485
619
@ Specialization
486
620
long find (PMMap primary , int sub , Object starting , @ SuppressWarnings ("unused" ) Object ending ,
487
- @ Cached ("create ()" ) ReadByteFromChannelNode readByteNode ) {
621
+ @ Cached ("createValueError ()" ) ReadByteFromChannelNode readByteNode ) {
488
622
try {
489
623
SeekableByteChannel channel = primary .getChannel ();
490
624
long len1 = channel .size ();
0 commit comments