Skip to content

Commit 5642851

Browse files
committed
Refactoring of PosixModuleBuiltins.WriteNode
1 parent 03a719e commit 5642851

File tree

4 files changed

+95
-83
lines changed

4 files changed

+95
-83
lines changed

graalpython/com.oracle.graal.python.annotations/src/com/oracle/graal/python/annotations/ArgumentClinic.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,5 +132,9 @@ enum ClinicConversion {
132132
* {@link #defaultValue()}, and {@link #useDefaultForNone()}.
133133
*/
134134
CodePoint,
135+
/**
136+
* Corresponds to CPython's {@code Py_buffer} convertor.
137+
*/
138+
Buffer,
135139
}
136140
}

graalpython/com.oracle.graal.python.processor/src/com/oracle/graal/python/processor/ArgumentClinicModel.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ public static String getCodeSnippet(ArgumentClinic annotation, BuiltinAnnotation
7373
return format("JavaIntConversionNodeGen.create(%s, %s)", annotation.defaultValue(), annotation.useDefaultForNone());
7474
case CodePoint:
7575
return format("CodePointConversionNodeGen.create(\"%s\", %s, %s)", builtin.name, annotation.defaultValue(), annotation.useDefaultForNone());
76+
case Buffer:
77+
return "BufferConversionNodeGen.create()";
7678
case Index:
7779
return format("IndexConversionNodeGen.create(%s, %s)", annotation.defaultValue(), annotation.useDefaultForNone());
7880
case None:
@@ -107,6 +109,8 @@ private static String getConvertorImport(ArgumentClinic annotation) {
107109
return "IndexConversionNodeGen";
108110
case CodePoint:
109111
return "CodePointConversionNodeGen";
112+
case Buffer:
113+
return "BufferConversionNodeGen";
110114
case None:
111115
return "DefaultValueNode";
112116
default:
@@ -120,6 +124,7 @@ public static PrimitiveType[] getAcceptedPrimitiveTypes(ArgumentClinic annotatio
120124
return new PrimitiveType[]{PrimitiveType.Boolean};
121125
case String:
122126
case CodePoint:
127+
case Buffer:
123128
return new PrimitiveType[0];
124129
case Int:
125130
case Index:

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

Lines changed: 20 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,10 @@
9898
import com.oracle.graal.python.builtins.objects.PNone;
9999
import com.oracle.graal.python.builtins.objects.bytes.BytesNodes;
100100
import com.oracle.graal.python.builtins.objects.bytes.PBytes;
101-
import com.oracle.graal.python.builtins.objects.bytes.PBytesLike;
102101
import com.oracle.graal.python.builtins.objects.common.SequenceNodes;
103102
import com.oracle.graal.python.builtins.objects.common.SequenceNodes.LenNode;
104-
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
105103
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.GetItemDynamicNode;
106104
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.GetItemNode;
107-
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodesFactory.ToByteArrayNodeGen;
108105
import com.oracle.graal.python.builtins.objects.dict.PDict;
109106
import com.oracle.graal.python.builtins.objects.exception.OSErrorEnum;
110107
import com.oracle.graal.python.builtins.objects.floats.PFloat;
@@ -143,7 +140,6 @@
143140
import com.oracle.graal.python.runtime.exception.PythonExitException;
144141
import com.oracle.graal.python.runtime.sequence.PSequence;
145142
import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage;
146-
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
147143
import com.oracle.graal.python.util.FileDeleteShutdownHook;
148144
import com.oracle.graal.python.util.OverflowException;
149145
import com.oracle.truffle.api.CompilerDirectives;
@@ -161,7 +157,6 @@
161157
import com.oracle.truffle.api.dsl.Specialization;
162158
import com.oracle.truffle.api.dsl.TypeSystemReference;
163159
import com.oracle.truffle.api.frame.VirtualFrame;
164-
import com.oracle.truffle.api.interop.UnsupportedMessageException;
165160
import com.oracle.truffle.api.library.CachedLibrary;
166161
import com.oracle.truffle.api.profiles.BranchProfile;
167162
import com.oracle.truffle.api.profiles.ConditionProfile;
@@ -1146,95 +1141,37 @@ Object mkdirMode(VirtualFrame frame, Object pathArg, @SuppressWarnings("unused")
11461141
}
11471142
}
11481143

1149-
@Builtin(name = "write", minNumOfPositionalArgs = 2)
1144+
@Builtin(name = "write", minNumOfPositionalArgs = 2, parameterNames = {"fd", "str"})
1145+
@ArgumentClinic(name = "fd", conversion = ClinicConversion.Int, defaultValue = "-1")
1146+
@ArgumentClinic(name = "str", conversion = ClinicConversion.Buffer)
11501147
@GenerateNodeFactory
1151-
@TypeSystemReference(PythonArithmeticTypes.class)
1152-
public abstract static class WriteNode extends PythonFileNode {
1153-
@Child private SequenceStorageNodes.ToByteArrayNode toByteArrayNode;
1154-
private final BranchProfile gotException = BranchProfile.create();
1155-
private final BranchProfile notWritable = BranchProfile.create();
1156-
1157-
public abstract Object executeWith(VirtualFrame frame, Object fd, Object data);
1148+
public abstract static class WriteNode extends PythonBinaryClinicBuiltinNode {
1149+
@Override
1150+
protected ArgumentClinicProvider getArgumentClinic() {
1151+
return PosixModuleBuiltinsClinicProviders.WriteNodeClinicProviderGen.INSTANCE;
1152+
}
11581153

11591154
@TruffleBoundary(allowInlining = true, transferToInterpreterOnException = false)
1160-
private static Object writableOp(byte[] data, Object channel) throws IOException {
1161-
if (channel instanceof WritableByteChannel) {
1162-
return doWriteOp(data, channel);
1163-
}
1164-
return null;
1155+
private static int doWriteOp(byte[] data, WritableByteChannel channel) throws IOException {
1156+
return channel.write(ByteBuffer.wrap(data));
11651157
}
11661158

11671159
@Specialization
11681160
Object write(VirtualFrame frame, int fd, byte[] data,
1169-
@Cached("createClassProfile()") ValueProfile channelClassProfile) {
1170-
Channel channel = getResources().getFileChannel(fd, channelClassProfile);
1161+
@Cached("createClassProfile()") ValueProfile channelClassProfile,
1162+
@Cached BranchProfile gotExceptionProfile,
1163+
@Cached BranchProfile nonWritableChannelProfile) {
1164+
Channel channel = getContext().getResources().getFileChannel(fd, channelClassProfile);
1165+
if (!(channel instanceof WritableByteChannel)) {
1166+
nonWritableChannelProfile.enter();
1167+
throw raiseOSError(frame, OSErrorEnum.EBADF);
1168+
}
11711169
try {
1172-
Object ret = writableOp(data, channel);
1173-
if (ret != null) {
1174-
return ret;
1175-
}
1170+
return doWriteOp(data, (WritableByteChannel) channel);
11761171
} catch (Exception e) {
1177-
gotException.enter();
1172+
gotExceptionProfile.enter();
11781173
throw raiseOSError(frame, e);
11791174
}
1180-
notWritable.enter();
1181-
throw raiseOSError(frame, OSErrorEnum.EBADF);
1182-
}
1183-
1184-
@TruffleBoundary(allowInlining = true, transferToInterpreterOnException = false)
1185-
private static int doWriteOp(byte[] data, Object channel) throws IOException {
1186-
return ((WritableByteChannel) channel).write(ByteBuffer.wrap(data));
1187-
}
1188-
1189-
@Specialization
1190-
Object write(VirtualFrame frame, int fd, String data,
1191-
@Cached("createClassProfile()") ValueProfile channelClassProfile) {
1192-
return write(frame, fd, stringToBytes(data), channelClassProfile);
1193-
}
1194-
1195-
@TruffleBoundary
1196-
private static byte[] stringToBytes(String data) {
1197-
return data.getBytes();
1198-
}
1199-
1200-
@Specialization
1201-
Object write(VirtualFrame frame, int fd, PBytesLike data,
1202-
@Cached("createClassProfile()") ValueProfile channelClassProfile) {
1203-
return write(frame, fd, getByteArray(data.getSequenceStorage()), channelClassProfile);
1204-
}
1205-
1206-
@Specialization(limit = "getCallSiteInlineCacheMaxDepth()")
1207-
Object write(VirtualFrame frame, int fd, Object data,
1208-
@CachedLibrary("data") PythonObjectLibrary lib,
1209-
@Cached("createClassProfile()") ValueProfile channelClassProfile) {
1210-
if (lib.isBuffer(data)) {
1211-
try {
1212-
byte[] b = lib.getBufferBytes(data);
1213-
return write(frame, fd, b, channelClassProfile);
1214-
} catch (UnsupportedMessageException e) {
1215-
throw CompilerDirectives.shouldNotReachHere("Buffer-like object does not support getBufferBytes()");
1216-
}
1217-
}
1218-
throw raise(TypeError, ErrorMessages.BYTESLIKE_OBJ_REQUIRED, data);
1219-
}
1220-
1221-
@Specialization(limit = "getCallSiteInlineCacheMaxDepth()")
1222-
static Object writePInt(VirtualFrame frame, Object fd, Object data,
1223-
@CachedLibrary("fd") PythonObjectLibrary lib,
1224-
@Cached("create()") WriteNode recursive) {
1225-
return recursive.executeWith(frame, lib.asSizeWithState(fd, PArguments.getThreadState(frame)), data);
1226-
}
1227-
1228-
private byte[] getByteArray(SequenceStorage storage) {
1229-
if (toByteArrayNode == null) {
1230-
CompilerDirectives.transferToInterpreterAndInvalidate();
1231-
toByteArrayNode = insert(ToByteArrayNodeGen.create());
1232-
}
1233-
return toByteArrayNode.execute(storage);
1234-
}
1235-
1236-
public static WriteNode create() {
1237-
return PosixModuleBuiltinsFactory.WriteNodeFactory.create(null);
12381175
}
12391176
}
12401177

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright (c) 2020, 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.nodes.function.builtins.clinic;
42+
43+
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
44+
import com.oracle.graal.python.nodes.ErrorMessages;
45+
import com.oracle.graal.python.nodes.function.builtins.clinic.ArgumentCastNode.ArgumentCastNodeWithRaise;
46+
import com.oracle.graal.python.runtime.exception.PythonErrorType;
47+
import com.oracle.truffle.api.CompilerDirectives;
48+
import com.oracle.truffle.api.dsl.Specialization;
49+
import com.oracle.truffle.api.interop.UnsupportedMessageException;
50+
import com.oracle.truffle.api.library.CachedLibrary;
51+
52+
public abstract class BufferConversionNode extends ArgumentCastNodeWithRaise {
53+
54+
@Specialization(limit = "getCallSiteInlineCacheMaxDepth()")
55+
byte[] doObject(Object value,
56+
@CachedLibrary("value") PythonObjectLibrary lib) {
57+
if (lib.isBuffer(value)) {
58+
try {
59+
return lib.getBufferBytes(value);
60+
} catch (UnsupportedMessageException e) {
61+
throw CompilerDirectives.shouldNotReachHere("Buffer-like object does not support getBufferBytes()");
62+
}
63+
}
64+
throw raise(PythonErrorType.TypeError, ErrorMessages.BYTESLIKE_OBJ_REQUIRED, value);
65+
}
66+
}

0 commit comments

Comments
 (0)