Skip to content

Commit 454af20

Browse files
lukasstadlerfangerer
authored andcommitted
eagerly convert sequences to native when the contents are requested
1 parent 0251776 commit 454af20

File tree

9 files changed

+108
-487
lines changed

9 files changed

+108
-487
lines changed

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

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
import java.lang.annotation.Retention;
8888
import java.lang.annotation.RetentionPolicy;
8989
import java.nio.ByteBuffer;
90+
import java.nio.ByteOrder;
9091
import java.util.ArrayList;
9192
import java.util.Arrays;
9293
import java.util.HashMap;
@@ -112,7 +113,6 @@
112113
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodesFactory.TransformExceptionToNativeNodeGen;
113114
import com.oracle.graal.python.builtins.objects.cext.capi.ExternalFunctionNodes.PExternalFunctionWrapper;
114115
import com.oracle.graal.python.builtins.objects.cext.capi.NativeCAPISymbol;
115-
import com.oracle.graal.python.builtins.objects.cext.capi.PySequenceArrayWrapper;
116116
import com.oracle.graal.python.builtins.objects.cext.capi.PythonClassNativeWrapper;
117117
import com.oracle.graal.python.builtins.objects.cext.capi.PythonNativePointer;
118118
import com.oracle.graal.python.builtins.objects.cext.capi.PythonNativeWrapper;
@@ -154,6 +154,7 @@
154154
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroStorageNode;
155155
import com.oracle.graal.python.lib.PyObjectGetAttr;
156156
import com.oracle.graal.python.nodes.ErrorMessages;
157+
import com.oracle.graal.python.nodes.PConstructAndRaiseNode;
157158
import com.oracle.graal.python.nodes.PGuards;
158159
import com.oracle.graal.python.nodes.PNodeWithContext;
159160
import com.oracle.graal.python.nodes.PNodeWithRaiseAndIndirectCall;
@@ -170,6 +171,7 @@
170171
import com.oracle.graal.python.nodes.util.CannotCastException;
171172
import com.oracle.graal.python.nodes.util.CastToJavaIntExactNode;
172173
import com.oracle.graal.python.runtime.PosixSupportLibrary;
174+
import com.oracle.graal.python.runtime.PosixSupportLibrary.PosixException;
173175
import com.oracle.graal.python.runtime.PythonContext;
174176
import com.oracle.graal.python.runtime.PythonContext.GetThreadStateNode;
175177
import com.oracle.graal.python.runtime.PythonOptions;
@@ -202,6 +204,7 @@
202204
import com.oracle.truffle.api.frame.FrameInstanceVisitor;
203205
import com.oracle.truffle.api.frame.VirtualFrame;
204206
import com.oracle.truffle.api.interop.InteropLibrary;
207+
import com.oracle.truffle.api.interop.InvalidBufferOffsetException;
205208
import com.oracle.truffle.api.interop.TruffleObject;
206209
import com.oracle.truffle.api.interop.UnsupportedMessageException;
207210
import com.oracle.truffle.api.library.CachedLibrary;
@@ -1757,6 +1760,80 @@ Object set(TruffleString tsName, Object pointer,
17571760
}
17581761
}
17591762

1763+
/**
1764+
* A native wrapper for arbitrary byte arrays (i.e. the store of a Python Bytes object) to be
1765+
* used like a {@code char*} pointer.
1766+
*/
1767+
@ExportLibrary(InteropLibrary.class)
1768+
public static final class PMMapWrapper implements TruffleObject {
1769+
1770+
private final PMMap delegate;
1771+
1772+
public PMMapWrapper(PMMap delegate) {
1773+
this.delegate = delegate;
1774+
}
1775+
1776+
@ExportMessage
1777+
@SuppressWarnings("static-method")
1778+
boolean hasBufferElements() {
1779+
return true;
1780+
}
1781+
1782+
@ExportMessage
1783+
long getBufferSize() {
1784+
return delegate.getLength();
1785+
}
1786+
1787+
private final void checkIndex(long idx) throws InvalidBufferOffsetException {
1788+
long len = delegate.getLength();
1789+
if (idx < 0 || idx >= len) {
1790+
throw InvalidBufferOffsetException.create(idx, len);
1791+
}
1792+
}
1793+
1794+
@ExportMessage
1795+
byte readBufferByte(long idx,
1796+
@CachedLibrary(limit = "1") PosixSupportLibrary posixSupportLib,
1797+
@Cached PConstructAndRaiseNode raise) throws InvalidBufferOffsetException {
1798+
checkIndex(idx);
1799+
try {
1800+
return (posixSupportLib.mmapReadByte(PythonContext.get(posixSupportLib).getPosixSupport(), delegate.getPosixSupportHandle(), idx));
1801+
} catch (PosixException e) {
1802+
throw raise.raiseOSError(null, e.getErrorCode(), e.getMessageAsTruffleString(), null, null);
1803+
}
1804+
}
1805+
1806+
@ExportMessage
1807+
@SuppressWarnings({"static-method", "unused"})
1808+
short readBufferShort(ByteOrder order, long byteOffset) throws UnsupportedMessageException {
1809+
throw UnsupportedMessageException.create();
1810+
}
1811+
1812+
@ExportMessage
1813+
@SuppressWarnings({"static-method", "unused"})
1814+
int readBufferInt(ByteOrder order, long byteOffset) throws UnsupportedMessageException {
1815+
throw UnsupportedMessageException.create();
1816+
}
1817+
1818+
@ExportMessage
1819+
@SuppressWarnings({"static-method", "unused"})
1820+
long readBufferLong(ByteOrder order, long byteOffset) throws UnsupportedMessageException {
1821+
throw UnsupportedMessageException.create();
1822+
}
1823+
1824+
@ExportMessage
1825+
@SuppressWarnings({"static-method", "unused"})
1826+
float readBufferFloat(ByteOrder order, long byteOffset) throws UnsupportedMessageException {
1827+
throw UnsupportedMessageException.create();
1828+
}
1829+
1830+
@ExportMessage
1831+
@SuppressWarnings({"static-method", "unused"})
1832+
double readBufferDouble(ByteOrder order, long byteOffset) throws UnsupportedMessageException {
1833+
throw UnsupportedMessageException.create();
1834+
}
1835+
}
1836+
17601837
@CApiBuiltin(ret = CHAR_PTR, args = {PyObject}, call = Ignored)
17611838
abstract static class PyTruffle_GetMMapData extends CApiUnaryBuiltinNode {
17621839

@@ -1766,7 +1843,7 @@ Object get(PMMap object,
17661843
try {
17671844
return posixLib.mmapGetPointer(getPosixSupport(), object.getPosixSupportHandle());
17681845
} catch (PosixSupportLibrary.UnsupportedPosixFeatureException e) {
1769-
return new PySequenceArrayWrapper(object, 1);
1846+
return new PMMapWrapper(object);
17701847
}
17711848
}
17721849
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextBytesBuiltins.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ static int doBytes(Object bytes,
399399
abstract static class PyBytes_AsString extends CApiUnaryBuiltinNode {
400400
@Specialization
401401
static Object doBytes(PBytes bytes) {
402-
return new PySequenceArrayWrapper(bytes, 1);
402+
return PySequenceArrayWrapper.ensureNativeSequence(bytes);
403403
}
404404

405405
@Specialization

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextSlotBuiltins.java

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@
163163
import com.oracle.graal.python.runtime.sequence.PSequence;
164164
import com.oracle.graal.python.runtime.sequence.storage.NativeByteSequenceStorage;
165165
import com.oracle.graal.python.runtime.sequence.storage.NativeObjectSequenceStorage;
166-
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
167166
import com.oracle.truffle.api.CompilerDirectives;
168167
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
169168
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -178,7 +177,6 @@
178177
import com.oracle.truffle.api.nodes.Node;
179178
import com.oracle.truffle.api.object.DynamicObjectLibrary;
180179
import com.oracle.truffle.api.profiles.ConditionProfile;
181-
import com.oracle.truffle.api.profiles.ValueProfile;
182180
import com.oracle.truffle.api.strings.TruffleString;
183181

184182
public final class PythonCextSlotBuiltins {
@@ -188,14 +186,9 @@ public final class PythonCextSlotBuiltins {
188186
abstract static class Py_get_PSequence_ob_item extends CApiUnaryBuiltinNode {
189187

190188
@Specialization
191-
static Object get(PSequence object,
192-
@Cached("createClassProfile()") ValueProfile classProfile) {
193-
SequenceStorage sequenceStorage = classProfile.profile(object.getSequenceStorage());
194-
assert !(sequenceStorage instanceof NativeByteSequenceStorage);
195-
if (sequenceStorage instanceof NativeObjectSequenceStorage) {
196-
return ((NativeObjectSequenceStorage) sequenceStorage).getPtr();
197-
}
198-
return new PySequenceArrayWrapper(object, 4);
189+
static Object get(PSequence object) {
190+
assert !(object.getSequenceStorage() instanceof NativeByteSequenceStorage);
191+
return PySequenceArrayWrapper.ensureNativeSequence(object);
199192
}
200193
}
201194

@@ -276,7 +269,12 @@ abstract static class Py_get_PyASCIIObject_wstr extends CApiUnaryBuiltinNode {
276269
static Object get(Object object,
277270
@Cached UnicodeAsWideCharNode asWideCharNode) {
278271
int elementSize = CStructs.wchar_t.size();
279-
return new PySequenceArrayWrapper(asWideCharNode.executeNativeOrder(object, elementSize), elementSize);
272+
/*
273+
* TODO: the string might get GC'd, since the object isn't referenced from anywhere. The
274+
* proper solution needs to differentiate here, and maybe use the "toNative" of
275+
* TruffleString.
276+
*/
277+
return PySequenceArrayWrapper.ensureNativeSequence(asWideCharNode.executeNativeOrder(object, elementSize));
280278
}
281279
}
282280

@@ -344,14 +342,9 @@ static int get(@SuppressWarnings("unused") Object object) {
344342
abstract static class Py_get_PyByteArrayObject_ob_start extends CApiUnaryBuiltinNode {
345343

346344
@Specialization
347-
static Object doObStart(PByteArray object,
348-
@Cached("createClassProfile()") ValueProfile classProfile) {
349-
SequenceStorage sequenceStorage = classProfile.profile(object.getSequenceStorage());
350-
assert !(sequenceStorage instanceof NativeObjectSequenceStorage);
351-
if (sequenceStorage instanceof NativeByteSequenceStorage) {
352-
return ((NativeByteSequenceStorage) sequenceStorage).getPtr();
353-
}
354-
return new PySequenceArrayWrapper(object, 1);
345+
static Object doObStart(PByteArray object) {
346+
assert !(object.getSequenceStorage() instanceof NativeObjectSequenceStorage);
347+
return PySequenceArrayWrapper.ensureNativeSequence(object);
355348
}
356349
}
357350

@@ -733,13 +726,11 @@ abstract static class Py_get_PyUnicodeObject_data extends CApiUnaryBuiltinNode {
733726
@Specialization
734727
static Object get(PString object,
735728
@Cached UnicodeAsWideCharNode asWideCharNode) {
736-
int elementSize = CStructs.wchar_t.size();
737-
738729
if (object.isNativeCharSequence()) {
739730
// in this case, we can just return the pointer
740731
return object.getNativeCharSequence().getPtr();
741732
}
742-
return new PySequenceArrayWrapper(asWideCharNode.executeNativeOrder(object, elementSize), elementSize);
733+
return PySequenceArrayWrapper.ensureNativeSequence(asWideCharNode.executeNativeOrder(object, CStructs.wchar_t.size()));
743734
}
744735
}
745736

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextUnicodeBuiltins.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -967,7 +967,7 @@ static Object doUnicode(PString s,
967967
PBytes bytes = (PBytes) asUTF8String.execute(s, T_STRICT);
968968
s.setUtf8Bytes(bytes);
969969
}
970-
return new PySequenceArrayWrapper(s.getUtf8Bytes(), 1);
970+
return PySequenceArrayWrapper.ensureNativeSequence(s.getUtf8Bytes());
971971
}
972972

973973
@Fallback
@@ -998,7 +998,7 @@ Object doUnicode(PString s,
998998
PBytes bytes = asWideCharNode.executeNativeOrder(s, CStructs.wchar_t.size());
999999
s.setWCharBytes(bytes);
10001000
}
1001-
return new PySequenceArrayWrapper(s.getWCharBytes(), 1);
1001+
return PySequenceArrayWrapper.ensureNativeSequence(s.getWCharBytes());
10021002
}
10031003

10041004
@Fallback

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

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@
7575
import com.oracle.graal.python.builtins.objects.PythonAbstractObject;
7676
import com.oracle.graal.python.builtins.objects.bytes.PByteArray;
7777
import com.oracle.graal.python.builtins.objects.bytes.PBytes;
78-
import com.oracle.graal.python.builtins.objects.bytes.PBytesLike;
7978
import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject;
8079
import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass;
8180
import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject;
@@ -526,33 +525,13 @@ static TruffleString doCStringWrapper(CStringWrapper cStringWrapper, @SuppressWa
526525

527526
@Specialization
528527
static TruffleString doCByteArrayWrapper(CByteArrayWrapper cByteArrayWrapper, boolean copy,
529-
@Shared("fromByteArray") @Cached TruffleString.FromByteArrayNode fromByteArrayNode,
528+
@Cached TruffleString.FromByteArrayNode fromByteArrayNode,
530529
@Shared("switchEncoding") @Cached TruffleString.SwitchEncodingNode switchEncodingNode) {
531530
CompilerAsserts.partialEvaluationConstant(copy);
532531
byte[] byteArray = cByteArrayWrapper.getByteArray();
533532
return switchEncodingNode.execute(fromByteArrayNode.execute(byteArray, 0, byteArray.length, Encoding.UTF_8, copy), TS_ENCODING);
534533
}
535534

536-
@Specialization
537-
static TruffleString doSequenceArrayWrapper(PySequenceArrayWrapper obj, boolean copy,
538-
@Cached SequenceStorageNodes.ToByteArrayNode toByteArrayNode,
539-
@Shared("fromByteArray") @Cached TruffleString.FromByteArrayNode fromByteArrayNode,
540-
@Shared("switchEncoding") @Cached TruffleString.SwitchEncodingNode switchEncodingNode) {
541-
CompilerAsserts.partialEvaluationConstant(copy);
542-
Object delegate = obj.getDelegate();
543-
boolean needs_copy;
544-
if (delegate instanceof PBytes) {
545-
// 'bytes' objects are immutable, so we can safely avoid a copy of the content
546-
needs_copy = false;
547-
} else if (delegate instanceof PByteArray) {
548-
needs_copy = copy;
549-
} else {
550-
throw CompilerDirectives.shouldNotReachHere();
551-
}
552-
byte[] bytes = toByteArrayNode.execute(((PBytesLike) delegate).getSequenceStorage());
553-
return switchEncodingNode.execute(fromByteArrayNode.execute(bytes, 0, bytes.length, Encoding.UTF_8, needs_copy), TS_ENCODING);
554-
}
555-
556535
@Specialization(guards = "!isCArrayWrapper(charPtr)", limit = "3")
557536
static TruffleString doPointer(Object charPtr, boolean copy,
558537
@Cached CStructAccess.ReadByteNode read,

0 commit comments

Comments
 (0)