Skip to content

Commit 1750f28

Browse files
committed
Support module 'mmap'.
1 parent 41a821e commit 1750f28

File tree

7 files changed

+321
-19
lines changed

7 files changed

+321
-19
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@
134134
import com.oracle.graal.python.builtins.objects.method.DecoratedMethodBuiltins;
135135
import com.oracle.graal.python.builtins.objects.method.MethodBuiltins;
136136
import com.oracle.graal.python.builtins.objects.method.StaticmethodBuiltins;
137+
import com.oracle.graal.python.builtins.objects.mmap.MMapBuiltins;
137138
import com.oracle.graal.python.builtins.objects.module.PythonModule;
138139
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltins;
139140
import com.oracle.graal.python.builtins.objects.object.PythonObject;
@@ -331,7 +332,8 @@ private static final PythonBuiltins[] initializeBuiltins(Env env) {
331332
new ZipImportModuleBuiltins(),
332333
new ZLibModuleBuiltins(),
333334
new MMapModuleBuiltins(),
334-
new FcntlModuleBuiltins()));
335+
new FcntlModuleBuiltins(),
336+
new MMapBuiltins()));
335337
if (!TruffleOptions.AOT) {
336338
ServiceLoader<PythonBuiltins> providers = ServiceLoader.load(PythonBuiltins.class);
337339
for (PythonBuiltins builtin : providers) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ public enum PythonBuiltinClassType implements LazyPythonClass {
6767
PMappingproxy("mappingproxy"),
6868
PMemoryView("memoryview", "builtins"),
6969
PMethod("method"),
70+
PMMap("mmap", "mmap"),
7071
PNone("NoneType"),
7172
PNotImplemented("NotImplementedType"),
7273
PRandom("Random", "_random"),

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

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,22 +40,81 @@
4040
*/
4141
package com.oracle.graal.python.builtins.modules;
4242

43+
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.PMMap;
44+
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.ValueError;
45+
46+
import java.nio.channels.Channel;
47+
import java.nio.channels.FileChannel.MapMode;
48+
import java.nio.channels.SeekableByteChannel;
4349
import java.util.List;
4450

51+
import com.oracle.graal.python.builtins.Builtin;
4552
import com.oracle.graal.python.builtins.CoreFunctions;
4653
import com.oracle.graal.python.builtins.PythonBuiltins;
54+
import com.oracle.graal.python.builtins.objects.PNone;
55+
import com.oracle.graal.python.builtins.objects.mmap.PMMap;
56+
import com.oracle.graal.python.builtins.objects.type.LazyPythonClass;
4757
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
58+
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
59+
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
4860
import com.oracle.truffle.api.dsl.NodeFactory;
61+
import com.oracle.truffle.api.dsl.Specialization;
62+
import com.oracle.truffle.api.profiles.ValueProfile;
4963

5064
@CoreFunctions(defineModule = "mmap")
5165
public class MMapModuleBuiltins extends PythonBuiltins {
66+
private static final int ACCESS_DEFAULT = 0;
67+
private static final int ACCESS_READ = 1;
68+
private static final int ACCESS_WRITE = 2;
69+
private static final int ACCESS_COPY = 3;
5270

5371
@Override
5472
protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFactories() {
55-
return ZipImportModuleBuiltinsFactory.getFactories();
73+
return MMapModuleBuiltinsFactory.getFactories();
5674
}
5775

5876
public MMapModuleBuiltins() {
77+
builtinConstants.put("ACCESS_DEFAULT", ACCESS_DEFAULT);
78+
builtinConstants.put("ACCESS_READ", ACCESS_READ);
79+
builtinConstants.put("ACCESS_WRITE", ACCESS_WRITE);
80+
builtinConstants.put("ACCESS_COPY", ACCESS_COPY);
5981
}
6082

83+
@Builtin(name = "mmap", fixedNumOfPositionalArgs = 3, keywordArguments = {"tagname", "access"}, constructsClass = PMMap)
84+
@GenerateNodeFactory
85+
public abstract static class MMapNode extends PythonBuiltinNode {
86+
87+
private final ValueProfile classProfile = ValueProfile.createClassProfile();
88+
89+
@Specialization(guards = {"isNoValue(access)"})
90+
PMMap doIt(LazyPythonClass clazz, int fd, int length, Object tagname, @SuppressWarnings("unused") PNone access) {
91+
return doGeneric(clazz, fd, length, tagname, ACCESS_DEFAULT);
92+
}
93+
94+
// mmap(fileno, length, tagname=None, access=ACCESS_DEFAULT[, offset])
95+
@Specialization
96+
PMMap doGeneric(LazyPythonClass clazz, int fd, int length, @SuppressWarnings("unused") Object tagname, int access) {
97+
Channel fileChannel = getContext().getResources().getFileChannel(fd, classProfile);
98+
if (fileChannel instanceof SeekableByteChannel) {
99+
MapMode mode = convertAccessToMapMode(access);
100+
return factory().createMMap(clazz, (SeekableByteChannel) fileChannel);
101+
}
102+
throw raise(ValueError, "cannot mmap file");
103+
}
104+
105+
private MapMode convertAccessToMapMode(int access) {
106+
switch (access) {
107+
case 0:
108+
return MapMode.READ_WRITE;
109+
case 1:
110+
return MapMode.READ_ONLY;
111+
case 2:
112+
return MapMode.READ_WRITE;
113+
case 3:
114+
return MapMode.PRIVATE;
115+
}
116+
throw raise(ValueError, "mmap invalid access parameter.");
117+
}
118+
119+
}
61120
}
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
/*
2+
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.graal.python.builtins.objects.mmap;
42+
43+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__ADD__;
44+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__CONTAINS__;
45+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__EQ__;
46+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETITEM__;
47+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GE__;
48+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GT__;
49+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__LEN__;
50+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__LE__;
51+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__LT__;
52+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__MUL__;
53+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__NE__;
54+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__REPR__;
55+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__RMUL__;
56+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__STR__;
57+
58+
import java.io.IOException;
59+
import java.util.List;
60+
61+
import com.oracle.graal.python.builtins.Builtin;
62+
import com.oracle.graal.python.builtins.CoreFunctions;
63+
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
64+
import com.oracle.graal.python.builtins.PythonBuiltins;
65+
import com.oracle.graal.python.builtins.objects.exception.OSErrorEnum;
66+
import com.oracle.graal.python.nodes.SpecialMethodNames;
67+
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
68+
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
69+
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
70+
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
71+
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
72+
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
73+
import com.oracle.truffle.api.dsl.NodeFactory;
74+
import com.oracle.truffle.api.dsl.Specialization;
75+
import com.oracle.truffle.api.frame.VirtualFrame;
76+
77+
@CoreFunctions(extendClasses = PythonBuiltinClassType.PMMap)
78+
public class MMapBuiltins extends PythonBuiltins {
79+
80+
@Override
81+
protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFactories() {
82+
return MMapBuiltinsFactory.getFactories();
83+
}
84+
85+
@Builtin(name = __ADD__, fixedNumOfPositionalArgs = 2)
86+
@GenerateNodeFactory
87+
abstract static class AddNode extends PythonBinaryBuiltinNode {
88+
}
89+
90+
@Builtin(name = __MUL__, fixedNumOfPositionalArgs = 2)
91+
@GenerateNodeFactory
92+
abstract static class MulNode extends PythonBuiltinNode {
93+
}
94+
95+
@Builtin(name = __RMUL__, fixedNumOfPositionalArgs = 2)
96+
@GenerateNodeFactory
97+
abstract static class RMulNode extends MulNode {
98+
}
99+
100+
@Builtin(name = __CONTAINS__, fixedNumOfPositionalArgs = 2)
101+
@GenerateNodeFactory
102+
abstract static class ContainsNode extends PythonBinaryBuiltinNode {
103+
}
104+
105+
@Builtin(name = __LT__, fixedNumOfPositionalArgs = 2)
106+
@GenerateNodeFactory
107+
abstract static class LtNode extends PythonBinaryBuiltinNode {
108+
}
109+
110+
@Builtin(name = __LE__, fixedNumOfPositionalArgs = 2)
111+
@GenerateNodeFactory
112+
abstract static class LeNode extends PythonBinaryBuiltinNode {
113+
}
114+
115+
@Builtin(name = __GT__, fixedNumOfPositionalArgs = 2)
116+
@GenerateNodeFactory
117+
abstract static class GtNode extends PythonBinaryBuiltinNode {
118+
}
119+
120+
@Builtin(name = __GE__, fixedNumOfPositionalArgs = 2)
121+
@GenerateNodeFactory
122+
abstract static class GeNode extends PythonBinaryBuiltinNode {
123+
}
124+
125+
@Builtin(name = __NE__, fixedNumOfPositionalArgs = 2)
126+
@GenerateNodeFactory
127+
abstract static class NeNode extends PythonBinaryBuiltinNode {
128+
}
129+
130+
@Builtin(name = __EQ__, fixedNumOfPositionalArgs = 2)
131+
@GenerateNodeFactory
132+
abstract static class EqNode extends PythonBinaryBuiltinNode {
133+
}
134+
135+
@Builtin(name = __STR__, fixedNumOfPositionalArgs = 1)
136+
@GenerateNodeFactory
137+
abstract static class StrNode extends PythonUnaryBuiltinNode {
138+
}
139+
140+
@Builtin(name = __REPR__, fixedNumOfPositionalArgs = 1)
141+
@GenerateNodeFactory
142+
abstract static class ReprNode extends StrNode {
143+
}
144+
145+
@Builtin(name = __GETITEM__, fixedNumOfPositionalArgs = 2)
146+
@GenerateNodeFactory
147+
abstract static class GetItemNode extends PythonBinaryBuiltinNode {
148+
}
149+
150+
@Builtin(name = SpecialMethodNames.__SETITEM__, fixedNumOfPositionalArgs = 3)
151+
@GenerateNodeFactory
152+
abstract static class SetItemNode extends PythonTernaryBuiltinNode {
153+
154+
}
155+
156+
@Builtin(name = __LEN__, fixedNumOfPositionalArgs = 1)
157+
@GenerateNodeFactory
158+
public abstract static class LenNode extends PythonUnaryBuiltinNode {
159+
160+
}
161+
162+
@Builtin(name = SpecialMethodNames.__ENTER__, fixedNumOfPositionalArgs = 2)
163+
@GenerateNodeFactory
164+
abstract static class EnterNode extends PythonBuiltinNode {
165+
}
166+
167+
@Builtin(name = SpecialMethodNames.__EXIT__, fixedNumOfPositionalArgs = 2)
168+
@GenerateNodeFactory
169+
abstract static class ExitNode extends PythonBuiltinNode {
170+
}
171+
172+
@Builtin(name = "size", fixedNumOfPositionalArgs = 1)
173+
@GenerateNodeFactory
174+
abstract static class SizeNode extends PythonBuiltinNode {
175+
176+
@Specialization
177+
long size(VirtualFrame frame, PMMap self) {
178+
try {
179+
return self.getChannel().size();
180+
} catch (IOException e) {
181+
throw raiseOSError(frame, OSErrorEnum.EIO, e.getMessage());
182+
}
183+
}
184+
}
185+
186+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.graal.python.builtins.objects.mmap;
42+
43+
import java.nio.channels.SeekableByteChannel;
44+
45+
import com.oracle.graal.python.builtins.objects.object.PythonObject;
46+
import com.oracle.graal.python.builtins.objects.type.LazyPythonClass;
47+
48+
public class PMMap extends PythonObject {
49+
50+
private final SeekableByteChannel mappedByteBuffer;
51+
52+
public PMMap(LazyPythonClass pythonClass, SeekableByteChannel mappedByteBuffer) {
53+
super(pythonClass);
54+
this.mappedByteBuffer = mappedByteBuffer;
55+
}
56+
57+
public SeekableByteChannel getChannel() {
58+
return mappedByteBuffer;
59+
}
60+
61+
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import java.lang.ref.ReferenceQueue;
2929
import java.math.BigInteger;
30+
import java.nio.channels.SeekableByteChannel;
3031
import java.nio.file.DirectoryStream;
3132
import java.util.Map;
3233
import java.util.Optional;
@@ -87,6 +88,7 @@
8788
import com.oracle.graal.python.builtins.objects.method.PBuiltinMethod;
8889
import com.oracle.graal.python.builtins.objects.method.PDecoratedMethod;
8990
import com.oracle.graal.python.builtins.objects.method.PMethod;
91+
import com.oracle.graal.python.builtins.objects.mmap.PMMap;
9092
import com.oracle.graal.python.builtins.objects.module.PythonModule;
9193
import com.oracle.graal.python.builtins.objects.object.PythonObject;
9294
import com.oracle.graal.python.builtins.objects.posix.PDirEntry;
@@ -839,4 +841,12 @@ public PDirEntry createDirEntry(String name, TruffleFile file) {
839841
public Object createDirEntry(LazyPythonClass cls, String name, TruffleFile file) {
840842
return trace(new PDirEntry(cls, name, file));
841843
}
844+
845+
public PMMap createMMap(SeekableByteChannel channel) {
846+
return trace(new PMMap(PythonBuiltinClassType.PMMap, channel));
847+
}
848+
849+
public PMMap createMMap(LazyPythonClass clazz, SeekableByteChannel channel) {
850+
return trace(new PMMap(clazz, channel));
851+
}
842852
}

0 commit comments

Comments
 (0)