Skip to content

Commit 86bfe1f

Browse files
committed
Support anonymous mmap.
1 parent 31d6783 commit 86bfe1f

File tree

1 file changed

+78
-4
lines changed

1 file changed

+78
-4
lines changed

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

Lines changed: 78 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545

4646
import java.io.IOException;
4747
import java.nio.channels.FileChannel.MapMode;
48+
import java.nio.ByteBuffer;
49+
import java.nio.channels.ByteChannel;
4850
import java.nio.channels.SeekableByteChannel;
4951
import java.nio.file.StandardOpenOption;
5052
import java.util.HashSet;
@@ -64,6 +66,7 @@
6466
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
6567
import com.oracle.truffle.api.dsl.NodeFactory;
6668
import com.oracle.truffle.api.dsl.Specialization;
69+
import com.oracle.truffle.api.profiles.BranchProfile;
6770
import com.oracle.truffle.api.profiles.ValueProfile;
6871

6972
@CoreFunctions(defineModule = "mmap")
@@ -90,15 +93,24 @@ public MMapModuleBuiltins() {
9093
public abstract static class MMapNode extends PythonBuiltinNode {
9194

9295
private final ValueProfile classProfile = ValueProfile.createClassProfile();
96+
private final BranchProfile invalidLengthProfile = BranchProfile.create();
9397

94-
@Specialization(guards = {"isNoValue(access)", "isNoValue(offset)"})
98+
@Specialization(guards = {"fd < 0", "isNoValue(access)", "isNoValue(offset)"})
99+
PMMap doAnonymous(LazyPythonClass clazz, int fd, int length, Object tagname, @SuppressWarnings("unused") PNone access, @SuppressWarnings("unused") PNone offset) {
100+
checkLength(length);
101+
return new PMMap(clazz, new AnonymousMap(length), length, 0);
102+
}
103+
104+
@Specialization(guards = {"fd >= 0", "isNoValue(access)", "isNoValue(offset)"})
95105
PMMap doIt(LazyPythonClass clazz, int fd, int length, Object tagname, @SuppressWarnings("unused") PNone access, @SuppressWarnings("unused") PNone offset) {
96-
return doGeneric(clazz, fd, length, tagname, ACCESS_DEFAULT, 0);
106+
return doFile(clazz, fd, length, tagname, ACCESS_DEFAULT, 0);
97107
}
98108

99109
// mmap(fileno, length, tagname=None, access=ACCESS_DEFAULT[, offset])
100-
@Specialization
101-
PMMap doGeneric(LazyPythonClass clazz, int fd, int length, @SuppressWarnings("unused") Object tagname, int access, long offset) {
110+
@Specialization(guards = "fd >= 0")
111+
PMMap doFile(LazyPythonClass clazz, int fd, int length, @SuppressWarnings("unused") Object tagname, int access, long offset) {
112+
checkLength(length);
113+
102114
String path = getContext().getResources().getFilePath(fd);
103115
TruffleFile truffleFile = getContext().getEnv().getTruffleFile(path);
104116

@@ -133,5 +145,67 @@ private MapMode convertAccessToMapMode(int access) {
133145
throw raise(ValueError, "mmap invalid access parameter.");
134146
}
135147

148+
private void checkLength(int length) {
149+
if (length < 0) {
150+
invalidLengthProfile.enter();
151+
throw raise(PythonBuiltinClassType.OverflowError, "memory mapped length must be positive");
152+
}
153+
}
154+
155+
}
156+
157+
private static class AnonymousMap implements SeekableByteChannel {
158+
private final byte[] data;
159+
160+
private boolean open = true;
161+
private int cur;
162+
163+
public AnonymousMap(int cap) {
164+
this.data = new byte[cap];
165+
}
166+
167+
public boolean isOpen() {
168+
return open;
169+
}
170+
171+
public void close() throws IOException {
172+
open = false;
173+
}
174+
175+
public int read(ByteBuffer dst) throws IOException {
176+
int nread = Math.min(dst.remaining(), data.length - cur);
177+
dst.put(data, cur, nread);
178+
return nread;
179+
}
180+
181+
public int write(ByteBuffer src) throws IOException {
182+
int nwrite = Math.min(src.remaining(), data.length - cur);
183+
src.get(data, cur, nwrite);
184+
return nwrite;
185+
}
186+
187+
public long position() throws IOException {
188+
return cur;
189+
}
190+
191+
public SeekableByteChannel position(long newPosition) throws IOException {
192+
if (newPosition < 0 || newPosition >= data.length) {
193+
throw new IllegalArgumentException();
194+
}
195+
cur = (int) newPosition;
196+
return this;
197+
}
198+
199+
public long size() throws IOException {
200+
return data.length;
201+
}
202+
203+
public SeekableByteChannel truncate(long size) throws IOException {
204+
for (int i = 0; i < size; i++) {
205+
data[i] = 0;
206+
}
207+
return this;
208+
}
209+
136210
}
137211
}

0 commit comments

Comments
 (0)