Skip to content

Commit 25dbf66

Browse files
committed
[GR-31699] Add support for as_buffer protocol for native storage from manage side
PullRequest: graalpython/1818
2 parents 66c2d7b + 3c35220 commit 25dbf66

File tree

12 files changed

+129
-50
lines changed

12 files changed

+129
-50
lines changed

graalpython/com.oracle.graal.python.cext/src/capi.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,10 @@ double truffle_read_ob_fval(PyFloatObject* fobj) {
775775
return fobj->ob_fval;
776776
}
777777

778+
void truffle_memcpy_bytes(void *dest, size_t dest_offset, void *src, size_t src_offset, size_t len) {
779+
memcpy(dest + dest_offset, src + src_offset, len);
780+
}
781+
778782
/* called from Java to get number of bits per long digit */
779783
int32_t get_long_bits_in_digit() {
780784
return PYLONG_BITS_IN_DIGIT;

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

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.UnicodeEncodeError;
2929
import static com.oracle.graal.python.builtins.objects.cext.capi.NativeCAPISymbol.FUN_ADD_NATIVE_SLOTS;
3030
import static com.oracle.graal.python.builtins.objects.cext.capi.NativeCAPISymbol.FUN_PY_OBJECT_NEW;
31-
import static com.oracle.graal.python.builtins.objects.cext.capi.NativeCAPISymbol.FUN_PY_TRUFFLE_MEMORYVIEW_FROM_OBJECT;
3231
import static com.oracle.graal.python.builtins.objects.str.StringUtils.canEncodeUTF8;
3332
import static com.oracle.graal.python.builtins.objects.str.StringUtils.containsNullCharacter;
3433
import static com.oracle.graal.python.builtins.objects.type.TypeBuiltins.TYPE_ITEMSIZE;
@@ -108,6 +107,7 @@
108107
import com.oracle.graal.python.annotations.ArgumentClinic;
109108
import com.oracle.graal.python.builtins.Builtin;
110109
import com.oracle.graal.python.builtins.CoreFunctions;
110+
import com.oracle.graal.python.builtins.Python3Core;
111111
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
112112
import com.oracle.graal.python.builtins.PythonBuiltins;
113113
import com.oracle.graal.python.builtins.modules.WarningsModuleBuiltins.WarnNode;
@@ -116,6 +116,7 @@
116116
import com.oracle.graal.python.builtins.objects.PNotImplemented;
117117
import com.oracle.graal.python.builtins.objects.array.PArray;
118118
import com.oracle.graal.python.builtins.objects.bytes.BytesNodes;
119+
import com.oracle.graal.python.builtins.objects.bytes.BytesNodes.GetManagedBufferNode;
119120
import com.oracle.graal.python.builtins.objects.bytes.PByteArray;
120121
import com.oracle.graal.python.builtins.objects.bytes.PBytes;
121122
import com.oracle.graal.python.builtins.objects.bytes.PBytesLike;
@@ -242,8 +243,6 @@
242243
import com.oracle.graal.python.nodes.util.SplitArgsNode;
243244
import com.oracle.graal.python.parser.PythonSSTNodeFactory;
244245
import com.oracle.graal.python.runtime.ExecutionContext.IndirectCallContext;
245-
import com.oracle.graal.python.runtime.PythonContext;
246-
import com.oracle.graal.python.builtins.Python3Core;
247246
import com.oracle.graal.python.runtime.exception.PException;
248247
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
249248
import com.oracle.graal.python.runtime.sequence.storage.ObjectSequenceStorage;
@@ -308,6 +307,7 @@ PBytes doEmpty(VirtualFrame frame, Object cls, PNone source, PNone encoding, PNo
308307

309308
@Specialization(guards = "!isNoValue(source)")
310309
PBytes doCallBytes(VirtualFrame frame, Object cls, Object source, PNone encoding, PNone errors,
310+
@Cached GetManagedBufferNode getManagedBufferNode,
311311
@Cached GetClassNode getClassNode,
312312
@Cached ConditionProfile hasBytes,
313313
@Cached("create(__BYTES__)") LookupSpecialMethodNode lookupBytes,
@@ -328,13 +328,16 @@ PBytes doCallBytes(VirtualFrame frame, Object cls, Object source, PNone encoding
328328
throw raise(TypeError, ErrorMessages.RETURNED_NONBYTES, __BYTES__, bytes);
329329
}
330330
}
331-
return factory().createBytes(cls, bytesInitNode.execute(frame, source, encoding, errors));
331+
Object s = getManagedBufferNode.getBuffer(frame, getContext(), source);
332+
return factory().createBytes(cls, bytesInitNode.execute(frame, s, encoding, errors));
332333
}
333334

334335
@Specialization(guards = {"isNoValue(source) || (!isNoValue(encoding) || !isNoValue(errors))"})
335336
PBytes dontCallBytes(VirtualFrame frame, Object cls, Object source, Object encoding, Object errors,
337+
@Cached GetManagedBufferNode getManagedBufferNode,
336338
@Cached BytesNodes.BytesInitNode bytesInitNode) {
337-
return factory().createBytes(cls, bytesInitNode.execute(frame, source, encoding, errors));
339+
Object s = getManagedBufferNode.getBuffer(frame, getContext(), source);
340+
return factory().createBytes(cls, bytesInitNode.execute(frame, s, encoding, errors));
338341
}
339342
}
340343

@@ -2167,14 +2170,16 @@ Object typeNew(VirtualFrame frame, Object cls, Object wName, PTuple bases, PDict
21672170
@Cached GetMroStorageNode getMroStorageNode) {
21682171
// Determine the proper metatype to deal with this
21692172
String name = castStr.execute(wName);
2170-
Object metaclass = calculate_metaclass(frame, cls, bases, getClassNode, lib);
2171-
if (metaclass != cls) {
2172-
Object newFunc = getNewFuncNode.execute(metaclass);
2173+
Object metaclass = cls;
2174+
Object winner = calculateMetaclass(frame, metaclass, bases, getClassNode, lib);
2175+
if (winner != metaclass) {
2176+
Object newFunc = getNewFuncNode.execute(winner);
21732177
if (newFunc instanceof PBuiltinFunction && (((PBuiltinFunction) newFunc).getFunctionRootNode() == getRootNode())) {
2178+
metaclass = winner;
21742179
// the new metaclass has the same __new__ function as we are in, continue
21752180
} else {
21762181
// Pass it to the winner
2177-
callNewFuncNode.execute(frame, newFunc, new Object[]{metaclass, name, bases, namespaceOrig}, kwds);
2182+
return callNewFuncNode.execute(frame, newFunc, new Object[]{winner, name, bases, namespaceOrig}, kwds);
21782183
}
21792184
}
21802185

@@ -2710,7 +2715,7 @@ private PythonAbstractClass[] getMro(PythonAbstractClass pythonClass) {
27102715
return getMroNode.execute(pythonClass);
27112716
}
27122717

2713-
private Object calculate_metaclass(VirtualFrame frame, Object cls, PTuple bases, GetClassNode getClassNode, PythonObjectLibrary lib) {
2718+
private Object calculateMetaclass(VirtualFrame frame, Object cls, PTuple bases, GetClassNode getClassNode, PythonObjectLibrary lib) {
27142719
Object winner = cls;
27152720
for (Object base : ensureGetObjectArrayNode().execute(bases)) {
27162721
if (lib.lookupAttributeOnType(base, __MRO_ENTRIES__) != PNone.NO_VALUE) {
@@ -3381,20 +3386,8 @@ PMemoryView fromMemoryView(@SuppressWarnings("unused") Object cls, PMemoryView o
33813386

33823387
@Specialization
33833388
PMemoryView fromNative(VirtualFrame frame, @SuppressWarnings("unused") Object cls, PythonAbstractNativeObject object,
3384-
@CachedLanguage PythonLanguage language,
3385-
@Cached CExtNodes.ToSulongNode toSulongNode,
3386-
@Cached CExtNodes.AsPythonObjectNode asPythonObjectNode,
3387-
@Cached PCallCapiFunction callCapiFunction,
3388-
@Cached PythonCextBuiltins.DefaultCheckFunctionResultNode checkFunctionResultNode) {
3389-
PythonContext context = getContext();
3390-
Object state = IndirectCallContext.enter(frame, language, context, this);
3391-
try {
3392-
Object result = callCapiFunction.call(FUN_PY_TRUFFLE_MEMORYVIEW_FROM_OBJECT, toSulongNode.execute(object));
3393-
checkFunctionResultNode.execute(context, FUN_PY_TRUFFLE_MEMORYVIEW_FROM_OBJECT.getName(), result);
3394-
return (PMemoryView) asPythonObjectNode.execute(result);
3395-
} finally {
3396-
IndirectCallContext.exit(frame, language, getContextRef(), state);
3397-
}
3389+
@Cached GetManagedBufferNode getManagedBufferNode) {
3390+
return getManagedBufferNode.getMemoryView(frame, getContext(), object);
33983391
}
33993392

34003393
@Fallback

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4173,6 +4173,7 @@ abstract static class PyAtExit extends PythonUnaryBuiltinNode {
41734173
@TruffleBoundary
41744174
int doGeneric(Object funcPtr) {
41754175
getContext().registerAtexitHook(new ShutdownHook() {
4176+
@Override
41764177
public void call(@SuppressWarnings("unused") PythonContext context) {
41774178
try {
41784179
InteropLibrary.getUncached().execute(funcPtr);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/io/BufferedIOBaseBuiltins.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
6060
import com.oracle.graal.python.builtins.PythonBuiltins;
6161
import com.oracle.graal.python.builtins.objects.bytes.BytesNodes;
62+
import com.oracle.graal.python.builtins.objects.bytes.BytesNodes.GetManagedBufferNode;
6263
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
6364
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
6465
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
@@ -133,12 +134,14 @@ protected Object callRead(VirtualFrame frame, Object self, int len) {
133134
* implementation of cpython/Modules/_io/bufferedio.c:_bufferediobase_readinto_generic
134135
*/
135136
@Specialization
136-
Object readinto(VirtualFrame frame, Object self, Object buffer,
137+
Object readinto(VirtualFrame frame, Object self, Object b,
138+
@Cached GetManagedBufferNode getManagedBufferNode,
137139
@Cached("createReadIntoArg()") BytesNodes.GetByteLengthIfWritableNode getLength,
138140
@CachedLibrary(limit = "2") PythonObjectLibrary asByte,
139141
@Cached ConditionProfile isBuffer,
140142
@Cached ConditionProfile oversize,
141143
@Cached SequenceStorageNodes.BytesMemcpyNode memcpyNode) {
144+
Object buffer = getManagedBufferNode.getBuffer(frame, getContext(), b);
142145
int len = getLength.execute(frame, buffer);
143146
Object data = callRead(frame, self, len);
144147
if (isBuffer.profile(!asByte.isBuffer(data))) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/io/BufferedReaderMixinBuiltins.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
import com.oracle.graal.python.builtins.CoreFunctions;
7373
import com.oracle.graal.python.builtins.objects.PNone;
7474
import com.oracle.graal.python.builtins.objects.bytes.BytesNodes;
75+
import com.oracle.graal.python.builtins.objects.bytes.BytesNodes.GetManagedBufferNode;
7576
import com.oracle.graal.python.builtins.objects.bytes.BytesUtils;
7677
import com.oracle.graal.python.builtins.objects.bytes.PByteArray;
7778
import com.oracle.graal.python.builtins.objects.bytes.PBytes;
@@ -500,14 +501,16 @@ abstract static class ReadIntoNode extends PythonBinaryWithInitErrorBuiltinNode
500501
* implementation of cpython/Modules/_io/bufferedio.c:_buffered_readinto_generic
501502
*/
502503
@Specialization(guards = "self.isOK()")
503-
Object bufferedReadintoGeneric(VirtualFrame frame, PBuffered self, Object buffer,
504+
Object bufferedReadintoGeneric(VirtualFrame frame, PBuffered self, Object b,
505+
@Cached GetManagedBufferNode getManagedBufferNode,
504506
@Cached BufferedIONodes.EnterBufferedNode lock,
505507
@Cached("createReadIntoArg()") BytesNodes.GetByteLengthIfWritableNode getLen,
506508
@Cached BufferedIONodes.FlushAndRewindUnlockedNode flushAndRewindUnlockedNode,
507509
@Cached RawReadNode rawReadNode,
508510
@Cached FillBufferNode fillBufferNode,
509511
@Cached SequenceStorageNodes.BytesMemcpyNode memcpyNode) {
510512
checkIsClosedNode.execute(frame, self);
513+
Object buffer = getManagedBufferNode.getBuffer(frame, getContext(), b);
511514
int bufLen = getLen.execute(frame, buffer);
512515
try {
513516
lock.enter(self);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/io/BytesIOBuiltins.java

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
import com.oracle.graal.python.builtins.objects.PNone;
9595
import com.oracle.graal.python.builtins.objects.bytes.BytesBuiltins;
9696
import com.oracle.graal.python.builtins.objects.bytes.BytesNodes;
97+
import com.oracle.graal.python.builtins.objects.bytes.BytesNodes.GetManagedBufferNode;
9798
import com.oracle.graal.python.builtins.objects.bytes.PBytes;
9899
import com.oracle.graal.python.builtins.objects.common.HashingStorageLibrary;
99100
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
@@ -125,9 +126,7 @@
125126
import com.oracle.truffle.api.dsl.Specialization;
126127
import com.oracle.truffle.api.dsl.TypeSystemReference;
127128
import com.oracle.truffle.api.frame.VirtualFrame;
128-
import com.oracle.truffle.api.interop.UnsupportedMessageException;
129129
import com.oracle.truffle.api.library.CachedLibrary;
130-
import com.oracle.truffle.api.profiles.ConditionProfile;
131130

132131
@CoreFunctions(extendClasses = PythonBuiltinClassType.PBytesIO)
133132
public class BytesIOBuiltins extends PythonBuiltins {
@@ -351,22 +350,15 @@ Object readlines(PBytesIO self, int maxsize,
351350
@GenerateNodeFactory
352351
abstract static class ReadIntoNode extends ClosedCheckPythonBinaryBuiltinNode {
353352

354-
@Specialization(guards = {"self.hasBuf()", "!isPBytes(buffer)"}, limit = "2")
355-
Object readinto(VirtualFrame frame, PBytesIO self, Object buffer,
356-
@CachedLibrary("buffer") PythonObjectLibrary lib,
357-
@Cached ConditionProfile isBuffer,
353+
@Specialization(guards = "self.hasBuf()")
354+
Object readinto(VirtualFrame frame, PBytesIO self, Object b,
355+
@Cached GetManagedBufferNode getManagedBufferNode,
356+
@Cached("createReadIntoArg()") BytesNodes.GetByteLengthIfWritableNode getLen,
358357
@Cached SequenceStorageNodes.GetInternalByteArrayNode getBytes,
359358
@Cached SequenceStorageNodes.BytesMemcpyNode memcpyNode) {
360-
if (isBuffer.profile(!lib.isBuffer(buffer))) {
361-
return error(self, buffer);
362-
}
359+
Object buffer = getManagedBufferNode.getBuffer(frame, getContext(), b);
363360
/* adjust invalid sizes */
364-
int len;
365-
try {
366-
len = lib.getBufferLength(buffer);
367-
} catch (UnsupportedMessageException e) {
368-
throw CompilerDirectives.shouldNotReachHere();
369-
}
361+
int len = getLen.execute(frame, buffer);
370362
int n = self.getStringSize() - self.getPos();
371363
if (len > n) {
372364
len = n;
@@ -383,11 +375,6 @@ Object readinto(VirtualFrame frame, PBytesIO self, Object buffer,
383375

384376
return len;
385377
}
386-
387-
@Specialization(guards = {"self.hasBuf()", "isPBytes(buffer)"})
388-
Object error(@SuppressWarnings("unused") PBytesIO self, Object buffer) {
389-
throw raise(TypeError, "%s() argument must be read-write bytes-like object, not %p", READINTO, buffer);
390-
}
391378
}
392379

393380
@Builtin(name = TRUNCATE, minNumOfPositionalArgs = 1, parameterNames = {"$self", "size"})

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/io/FileIOBuiltins.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@
113113
import com.oracle.graal.python.builtins.objects.PNone;
114114
import com.oracle.graal.python.builtins.objects.bytes.BytesBuiltins;
115115
import com.oracle.graal.python.builtins.objects.bytes.BytesNodes;
116+
import com.oracle.graal.python.builtins.objects.bytes.BytesNodes.GetManagedBufferNode;
116117
import com.oracle.graal.python.builtins.objects.bytes.PBytes;
117118
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
118119
import com.oracle.graal.python.builtins.objects.exception.OSErrorEnum;
@@ -589,15 +590,17 @@ Object closedError(@SuppressWarnings("unused") PFileIO self) {
589590
abstract static class ReadintoNode extends PythonBinaryBuiltinNode {
590591

591592
@Specialization(guards = {"!self.isClosed()", "self.isReadable()"})
592-
Object readinto(VirtualFrame frame, PFileIO self, Object buffer,
593+
Object readinto(VirtualFrame frame, PFileIO self, Object b,
593594
@Cached PosixModuleBuiltins.ReadNode posixRead,
594595
@Cached BranchProfile readErrorProfile,
595596
@Cached SequenceStorageNodes.GetInternalByteArrayNode getBytes,
596597
@Cached SequenceStorageNodes.BytesMemcpyNode memcpyNode,
598+
@Cached GetManagedBufferNode getManagedBufferNode,
597599
@Cached("createReadIntoArg()") BytesNodes.GetByteLengthIfWritableNode getLen,
598600
@CachedLibrary(limit = "1") PosixSupportLibrary posixLib,
599601
@Cached BranchProfile exceptionProfile,
600602
@Cached GilNode gil) {
603+
Object buffer = getManagedBufferNode.getBuffer(frame, getContext(), b);
601604
int size = getLen.execute(frame, buffer);
602605
if (size == 0) {
603606
return 0;

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/ByteArrayBuiltins.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import com.oracle.graal.python.builtins.PythonBuiltins;
5050
import com.oracle.graal.python.builtins.objects.PNone;
5151
import com.oracle.graal.python.builtins.objects.bytes.BytesBuiltins.BytesLikeNoGeneralizationNode;
52+
import com.oracle.graal.python.builtins.objects.bytes.BytesNodes.GetManagedBufferNode;
5253
import com.oracle.graal.python.builtins.objects.common.IndexNodes;
5354
import com.oracle.graal.python.builtins.objects.common.IndexNodes.NormalizeIndexNode;
5455
import com.oracle.graal.python.builtins.objects.common.SequenceNodes;
@@ -142,9 +143,11 @@ protected ArgumentClinicProvider getArgumentClinic() {
142143
}
143144

144145
@Specialization(guards = "!isNone(source)")
145-
public static PNone doInit(VirtualFrame frame, PByteArray self, Object source, Object encoding, Object errors,
146+
public PNone doInit(VirtualFrame frame, PByteArray self, Object source, Object encoding, Object errors,
147+
@Cached GetManagedBufferNode getManagedBufferNode,
146148
@Cached BytesNodes.BytesInitNode toBytesNode) {
147-
self.setSequenceStorage(new ByteSequenceStorage(toBytesNode.execute(frame, source, encoding, errors)));
149+
Object s = getManagedBufferNode.getBuffer(frame, getContext(), source);
150+
self.setSequenceStorage(new ByteSequenceStorage(toBytesNode.execute(frame, s, encoding, errors)));
148151
return PNone.NONE;
149152
}
150153

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/bytes/BytesBuiltins.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2747,4 +2747,5 @@ PTuple doBytes(PBytes self) {
27472747
return factory().createTuple(new Object[]{factory().createBytes(self.getSequenceStorage())});
27482748
}
27492749
}
2750+
27502751
}

0 commit comments

Comments
 (0)