Skip to content

Commit 2c931de

Browse files
committed
Add PythonBufferAccessLibrary.getNativePointer
1 parent d1fb7f9 commit 2c931de

File tree

11 files changed

+209
-239
lines changed

11 files changed

+209
-239
lines changed

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

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import com.oracle.graal.python.builtins.objects.PNone;
6060
import com.oracle.graal.python.builtins.objects.buffer.PythonBufferAccessLibrary;
6161
import com.oracle.graal.python.builtins.objects.buffer.PythonBufferAcquireLibrary;
62+
import com.oracle.graal.python.builtins.objects.cext.common.NativePointer;
6263
import com.oracle.graal.python.builtins.objects.exception.PBaseException;
6364
import com.oracle.graal.python.builtins.objects.module.PythonModule;
6465
import com.oracle.graal.python.builtins.objects.object.PythonObject;
@@ -81,7 +82,6 @@
8182
import com.oracle.graal.python.nodes.function.builtins.PythonSenaryBuiltinNode;
8283
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
8384
import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes;
84-
import com.oracle.graal.python.nodes.util.BufferToTruffleStringNode;
8585
import com.oracle.graal.python.nodes.util.CannotCastException;
8686
import com.oracle.graal.python.nodes.util.CastToTruffleStringNode;
8787
import com.oracle.graal.python.runtime.IndirectCallData;
@@ -810,7 +810,7 @@ Object doCached(VirtualFrame frame, @SuppressWarnings("unused") Object callable,
810810
binaryProfile.enter(inliningTarget);
811811
// It's bytes or other buffer object
812812
buffer = bufferAcquireLib.acquireReadonly(inputStringOrBytes, frame, indirectCallData);
813-
input = getBufferToTruffleStringNode().execute(buffer, 0);
813+
input = getBufferToTruffleStringNode().execute(buffer);
814814
}
815815
try {
816816
return interop.invokeMember(cachedCallable, "exec", input, fromIndex);
@@ -844,5 +844,47 @@ private BufferToTruffleStringNode getBufferToTruffleStringNode() {
844844
}
845845
return bufferToTruffleStringNode;
846846
}
847+
848+
@GenerateInline(false)
849+
abstract static class BufferToTruffleStringNode extends PNodeWithContext {
850+
851+
public abstract TruffleString execute(Object buffer);
852+
853+
@Specialization(limit = "4")
854+
static TruffleString convert(Object buffer,
855+
@Bind("this") Node inliningTarget,
856+
@CachedLibrary(value = "buffer") PythonBufferAccessLibrary bufferLib,
857+
@Cached TruffleString.FromByteArrayNode fromByteArrayNode,
858+
@Cached TruffleString.FromNativePointerNode fromNativePointerNode,
859+
@Cached InlinedBranchProfile internalArrayProfile,
860+
@Cached InlinedBranchProfile nativeProfile,
861+
@Cached InlinedBranchProfile fallbackProfile) {
862+
PythonBufferAccessLibrary.assertIsBuffer(buffer);
863+
int len = bufferLib.getBufferLength(buffer);
864+
if (bufferLib.hasInternalByteArray(buffer)) {
865+
internalArrayProfile.enter(inliningTarget);
866+
byte[] bytes = bufferLib.getInternalByteArray(buffer);
867+
return fromByteArrayNode.execute(bytes, 0, len, TruffleString.Encoding.ISO_8859_1, false);
868+
}
869+
if (bufferLib.isNative(buffer)) {
870+
nativeProfile.enter(inliningTarget);
871+
Object ptr = bufferLib.getNativePointer(buffer);
872+
if (ptr != null) {
873+
if (ptr instanceof Long lptr) {
874+
ptr = new NativePointer(lptr);
875+
}
876+
return fromNativePointerNode.execute(ptr, 0, len, TruffleString.Encoding.ISO_8859_1, false);
877+
}
878+
}
879+
fallbackProfile.enter(inliningTarget);
880+
byte[] bytes = bufferLib.getCopiedByteArray(buffer);
881+
return fromByteArrayNode.execute(bytes, 0, len, TruffleString.Encoding.ISO_8859_1, false);
882+
}
883+
884+
@NeverDefault
885+
public static BufferToTruffleStringNode create() {
886+
return SREModuleBuiltinsFactory.TRegexCallExecFactory.BufferToTruffleStringNodeGen.create();
887+
}
888+
}
847889
}
848890
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/CDataObject.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,20 @@ void writeFromByteArray(int destOffset, byte[] src, int srcOffset, int length,
167167
writeBytesNode.execute(inliningTarget, b_ptr.withOffset(destOffset), src, srcOffset, length);
168168
}
169169

170+
@ExportMessage
171+
boolean isNative(
172+
@Bind("$node") Node inliningTarget,
173+
@Cached PointerNodes.PointerIsNativeNode pointerIsNativeNode) {
174+
return pointerIsNativeNode.execute(inliningTarget, b_ptr);
175+
}
176+
177+
@ExportMessage
178+
Object getNativePointer(
179+
@Bind("$node") Node inliningTarget,
180+
@Cached PointerNodes.GetPointerValueAsObjectNode getPointerValue) {
181+
return getPointerValue.execute(inliningTarget, b_ptr);
182+
}
183+
170184
// TODO we could expose the internal array if available
171185

172186
@SuppressWarnings("static-method")

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/memory/PointerNodes.java

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -55,18 +55,14 @@
5555
import com.oracle.graal.python.builtins.modules.ctypes.memory.Pointer.Storage;
5656
import com.oracle.graal.python.builtins.modules.ctypes.memory.Pointer.ZeroStorage;
5757
import com.oracle.graal.python.builtins.objects.buffer.PythonBufferAccessLibrary;
58-
import com.oracle.graal.python.builtins.objects.bytes.PBytesLike;
5958
import com.oracle.graal.python.builtins.objects.cext.PythonNativeVoidPtr;
6059
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes;
6160
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions;
62-
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
6361
import com.oracle.graal.python.builtins.objects.memoryview.PMemoryView;
6462
import com.oracle.graal.python.nodes.ErrorMessages;
6563
import com.oracle.graal.python.nodes.PRaiseNode;
6664
import com.oracle.graal.python.nodes.util.CastToJavaUnsignedLongNode;
6765
import com.oracle.graal.python.runtime.PythonContext;
68-
import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage;
69-
import com.oracle.graal.python.runtime.sequence.storage.NativeSequenceStorage;
7066
import com.oracle.graal.python.util.PythonUtils;
7167
import com.oracle.truffle.api.CompilerDirectives;
7268
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -662,31 +658,23 @@ static long doPointerArray(Node inliningTarget, MemoryBlock memory, PointerArray
662658
@Specialization
663659
static long doMemoryView(Node inliningTarget, MemoryBlock memory, MemoryViewStorage storage, int offset,
664660
@CachedLibrary(limit = "1") InteropLibrary ilib,
665-
@Cached SequenceStorageNodes.StorageToNativeNode storageToNativeNode) {
661+
@CachedLibrary(limit = "1") PythonBufferAccessLibrary bufferLib) {
666662
PMemoryView mv = storage.memoryView;
667-
Object ptr = null;
668-
if (mv.getBufferPointer() != null) {
669-
ptr = mv.getBufferPointer();
670-
} else if (mv.getBuffer() instanceof PBytesLike bytes) {
671-
if (bytes.getSequenceStorage() instanceof NativeSequenceStorage nativeSequenceStorage) {
672-
ptr = nativeSequenceStorage.getPtr();
673-
}
674-
if (bytes.getSequenceStorage() instanceof ByteSequenceStorage byteSequenceStorage) {
675-
NativeSequenceStorage nativeStorage = storageToNativeNode.execute(inliningTarget, byteSequenceStorage.getInternalByteArray(), byteSequenceStorage.length());
676-
bytes.setSequenceStorage(nativeStorage);
677-
ptr = nativeStorage.getPtr();
678-
}
679-
}
680-
if (ptr != null && ilib.isPointer(ptr)) {
663+
Object ptr = bufferLib.getNativePointer(mv);
664+
long nativePointer;
665+
if (ptr instanceof Long lptr) {
666+
nativePointer = lptr;
667+
} else if (ptr != null && ilib.isPointer(ptr)) {
681668
try {
682-
long nativePointer = ilib.asPointer(ptr);
683-
memory.storage = new LongPointerStorage(nativePointer);
684-
return nativePointer + offset;
669+
nativePointer = ilib.asPointer(ptr);
685670
} catch (UnsupportedMessageException e) {
686671
throw CompilerDirectives.shouldNotReachHere(e);
687672
}
673+
} else {
674+
throw PRaiseNode.raiseUncached(inliningTarget, NotImplementedError, ErrorMessages.MEMORYVIEW_CANNOT_BE_CONVERTED_TO_NATIVE_MEMORY);
688675
}
689-
throw PRaiseNode.raiseUncached(inliningTarget, NotImplementedError, ErrorMessages.MEMORYVIEW_CANNOT_BE_CONVERTED_TO_NATIVE_MEMORY);
676+
memory.storage = new LongPointerStorage(nativePointer);
677+
return nativePointer + offset;
690678
}
691679

692680
@Specialization
@@ -913,4 +901,30 @@ static ByteArrayStorage convert(Node inliningTarget, MemoryBlock memory, Pointer
913901
return newStorage;
914902
}
915903
}
904+
905+
@GenerateInline
906+
@GenerateCached(false)
907+
@GenerateUncached
908+
public abstract static class PointerIsNativeNode extends Node {
909+
public final boolean execute(Node inliningTarget, Pointer ptr) {
910+
return execute(inliningTarget, ptr.memory.storage);
911+
}
912+
913+
abstract boolean execute(Node inliningTarget, Storage storage);
914+
915+
@Specialization
916+
static boolean doLongPointer(@SuppressWarnings("unused") LongPointerStorage storage) {
917+
return true;
918+
}
919+
920+
@Specialization
921+
static boolean doObjectPointer(@SuppressWarnings("unused") ObjectPointerStorage storage) {
922+
return true;
923+
}
924+
925+
@Fallback
926+
static boolean doOther(@SuppressWarnings("unused") Storage storage) {
927+
return false;
928+
}
929+
}
916930
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/array/PArray.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
import com.oracle.graal.python.builtins.objects.buffer.PythonBufferAccessLibrary;
3939
import com.oracle.graal.python.builtins.objects.buffer.PythonBufferAcquireLibrary;
40+
import com.oracle.graal.python.builtins.objects.cext.capi.PySequenceArrayWrapper;
4041
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
4142
import com.oracle.graal.python.builtins.objects.ints.PInt;
4243
import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject;
@@ -45,6 +46,7 @@
4546
import com.oracle.graal.python.runtime.GilNode;
4647
import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage;
4748
import com.oracle.graal.python.runtime.sequence.storage.NativeByteSequenceStorage;
49+
import com.oracle.graal.python.runtime.sequence.storage.NativeSequenceStorage;
4850
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
4951
import com.oracle.graal.python.util.BufferFormat;
5052
import com.oracle.graal.python.util.OverflowException;
@@ -417,4 +419,18 @@ public boolean isArrayElementInsertable(long idx) {
417419
public boolean isArrayElementRemovable(long idx) {
418420
return isInBounds(idx);
419421
}
422+
423+
@ExportMessage
424+
boolean isNative() {
425+
return storage instanceof NativeByteSequenceStorage;
426+
}
427+
428+
@ExportMessage
429+
Object getNativePointer(
430+
@Bind("$node") Node inliningTarget,
431+
@Cached PySequenceArrayWrapper.ToNativeStorageNode toNativeStorageNode) {
432+
NativeSequenceStorage newStorage = toNativeStorageNode.execute(inliningTarget, storage, true);
433+
setSequenceStorage(newStorage);
434+
return newStorage.getPtr();
435+
}
420436
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/buffer/PythonBufferAccessLibrary.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -581,6 +581,24 @@ public TruffleString getFormatString(@SuppressWarnings("unused") Object receiver
581581
return T_UINT_8_TYPE_CODE;
582582
}
583583

584+
/**
585+
* Return if the buffer is backed by native memory.
586+
*/
587+
@Abstract(ifExported = "getNativePointer")
588+
public boolean isNative(@SuppressWarnings("unused") Object receiver) {
589+
return false;
590+
}
591+
592+
/**
593+
* Return the native pointer to the buffer. Should convert the buffer to native when possible.
594+
* Might return null when there is no native representation. The pointer can be either an
595+
* interop pointer or a long.
596+
*/
597+
@Abstract(ifExported = "isNative")
598+
public Object getNativePointer(@SuppressWarnings("unused") Object receiver) {
599+
return null;
600+
}
601+
584602
static final LibraryFactory<PythonBufferAccessLibrary> FACTORY = LibraryFactory.resolve(PythonBufferAccessLibrary.class);
585603

586604
public static LibraryFactory<PythonBufferAccessLibrary> getFactory() {

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,19 @@
4444

4545
import com.oracle.graal.python.builtins.objects.buffer.PythonBufferAccessLibrary;
4646
import com.oracle.graal.python.builtins.objects.buffer.PythonBufferAcquireLibrary;
47+
import com.oracle.graal.python.builtins.objects.cext.capi.PySequenceArrayWrapper;
4748
import com.oracle.graal.python.runtime.sequence.PSequence;
4849
import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage;
4950
import com.oracle.graal.python.runtime.sequence.storage.NativeByteSequenceStorage;
51+
import com.oracle.graal.python.runtime.sequence.storage.NativeSequenceStorage;
5052
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
53+
import com.oracle.truffle.api.dsl.Bind;
54+
import com.oracle.truffle.api.dsl.Cached;
5155
import com.oracle.truffle.api.dsl.Cached.Shared;
5256
import com.oracle.truffle.api.library.CachedLibrary;
5357
import com.oracle.truffle.api.library.ExportLibrary;
5458
import com.oracle.truffle.api.library.ExportMessage;
59+
import com.oracle.truffle.api.nodes.Node;
5560
import com.oracle.truffle.api.object.Shape;
5661

5762
@ExportLibrary(PythonBufferAcquireLibrary.class)
@@ -152,4 +157,18 @@ float readFloatByteOrder(int byteOffset, ByteOrder byteOrder,
152157
@Shared("bufferLib") @CachedLibrary(limit = "2") PythonBufferAccessLibrary bufferLib) {
153158
return bufferLib.readDoubleByteOrder(store, byteOffset, byteOrder);
154159
}
160+
161+
@ExportMessage
162+
boolean isNative() {
163+
return store instanceof NativeByteSequenceStorage;
164+
}
165+
166+
@ExportMessage
167+
Object getNativePointer(
168+
@Bind("$node") Node inliningTarget,
169+
@Cached PySequenceArrayWrapper.ToNativeStorageNode toNativeStorageNode) {
170+
NativeSequenceStorage newStorage = toNativeStorageNode.execute(inliningTarget, store, true);
171+
setSequenceStorage(newStorage);
172+
return newStorage.getPtr();
173+
}
155174
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CExtNodes.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242

4343
import static com.oracle.graal.python.builtins.objects.PNone.NO_VALUE;
4444
import static com.oracle.graal.python.builtins.objects.cext.capi.NativeCAPISymbol.FUN_NO_OP_CLEAR;
45-
import static com.oracle.graal.python.builtins.objects.cext.capi.NativeCAPISymbol.FUN_PTR_ADD;
4645
import static com.oracle.graal.python.builtins.objects.cext.capi.NativeCAPISymbol.FUN_PTR_COMPARE;
4746
import static com.oracle.graal.python.builtins.objects.cext.capi.NativeCAPISymbol.FUN_PY_DEALLOC;
4847
import static com.oracle.graal.python.builtins.objects.cext.capi.NativeCAPISymbol.FUN_PY_OBJECT_GC_DEL;
@@ -648,11 +647,6 @@ static boolean isNativeObjectOrLong(Object object) {
648647
}
649648
}
650649

651-
@TruffleBoundary
652-
public static Object pointerAdd(Object pointer, long offset) {
653-
return PCallCapiFunction.callUncached(FUN_PTR_ADD, pointer, offset);
654-
}
655-
656650
// -----------------------------------------------------------------------------------------------------------------
657651

658652
/**

0 commit comments

Comments
 (0)