Skip to content

Commit 490cdbb

Browse files
committed
Add helpers bytes nodes
1 parent 8608723 commit 490cdbb

File tree

3 files changed

+108
-28
lines changed

3 files changed

+108
-28
lines changed

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
package com.oracle.graal.python.builtins.objects.bytes;
4242

4343
import static com.oracle.graal.python.PythonLanguage.getCore;
44+
import static com.oracle.graal.python.nodes.ErrorMessages.EXPECTED_BYTESLIKE_GOT_P;
4445
import static com.oracle.graal.python.runtime.exception.PythonErrorType.MemoryError;
4546
import static com.oracle.graal.python.runtime.exception.PythonErrorType.TypeError;
4647
import static com.oracle.graal.python.runtime.exception.PythonErrorType.ValueError;
@@ -195,7 +196,6 @@ public static BytesJoinNode create() {
195196

196197
@ImportStatic({PGuards.class, SpecialMethodNames.class})
197198
public abstract static class ToBytesNode extends PNodeWithRaise {
198-
private static final String DEFAULT_FORMAT = "expected a bytes-like object, %p found";
199199

200200
private final PythonBuiltinClassType errorType;
201201
private final String errorMessageFormat;
@@ -235,7 +235,7 @@ byte[] doError(Object obj) {
235235
}
236236

237237
public static ToBytesNode create() {
238-
return ToBytesNodeGen.create(TypeError, DEFAULT_FORMAT);
238+
return ToBytesNodeGen.create(TypeError, EXPECTED_BYTESLIKE_GOT_P);
239239
}
240240

241241
public static ToBytesNode create(PythonBuiltinClassType errorType, String errorMessageFormat) {
@@ -380,6 +380,7 @@ protected int emptySubIndex(int start, int end) {
380380
return (end - start) + start;
381381
}
382382

383+
@TruffleBoundary(allowInlining = true)
383384
@Override
384385
protected int findSubSequence(byte[] haystack, byte[] needle, int len2, int start, int end) {
385386
// TODO implement a more efficient algorithm
@@ -391,6 +392,7 @@ protected int findSubSequence(byte[] haystack, byte[] needle, int len2, int star
391392
return -1;
392393
}
393394

395+
@TruffleBoundary(allowInlining = true)
394396
@Override
395397
protected int findElement(byte[] haystack, byte sub, int start, int end) {
396398
for (int i = end - 1; i >= start; i--) {

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

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -346,21 +346,19 @@ public static Object doAsciiString(String str) {
346346
byte[] bytes = unicodeEscape(str);
347347
boolean hasSingleQuote = false;
348348
boolean hasDoubleQuote = false;
349-
for (int i = 0; i < bytes.length; i++) {
350-
char c = (char) bytes[i];
351-
hasSingleQuote |= c == '\'';
352-
hasDoubleQuote |= c == '"';
349+
for (byte b : bytes) {
350+
hasSingleQuote |= b == '\'';
351+
hasDoubleQuote |= b == '"';
353352
}
354353
boolean useDoubleQuotes = hasSingleQuote && !hasDoubleQuote;
355354
char quote = useDoubleQuotes ? '"' : '\'';
356355
StringBuilder sb = PythonUtils.newStringBuilder(bytes.length + 2);
357356
PythonUtils.append(sb, quote);
358-
for (int i = 0; i < bytes.length; i++) {
359-
char c = (char) bytes[i];
360-
if (c == '\'' && !useDoubleQuotes) {
357+
for (byte b : bytes) {
358+
if (b == '\'' && !useDoubleQuotes) {
361359
PythonUtils.append(sb, "\\'");
362360
} else {
363-
PythonUtils.append(sb, c);
361+
PythonUtils.append(sb, (char) b);
364362
}
365363
}
366364
PythonUtils.append(sb, quote);
@@ -400,7 +398,7 @@ private static void byteRepr(StringBuilder sb, byte b, boolean isSingleQuote) {
400398
} else if (b == '\r') {
401399
PythonUtils.append(sb, "\\r");
402400
} else if (b == '\'') {
403-
PythonUtils.append(sb, isSingleQuote ? "\\'" : "\'");
401+
PythonUtils.append(sb, isSingleQuote ? "\\'" : "'");
404402
} else if (b > 31 && b <= 126) {
405403
char chr = (char) b;
406404
if (chr == '\\') {
@@ -718,6 +716,16 @@ public static int digitValue(byte hexChar) {
718716
return 37;
719717
}
720718

719+
@TruffleBoundary(allowInlining = true)
720+
public static int memchr(byte[] bytes, int start, byte v, int len) {
721+
for (int i = start; i < start + len; i++) {
722+
if (bytes[i] == v) {
723+
return i;
724+
}
725+
}
726+
return -1;
727+
}
728+
721729
@TruffleBoundary
722730
public static String createASCIIString(byte[] retbuf) {
723731
return new String(retbuf, StandardCharsets.US_ASCII);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/SequenceStorageNodes.java

Lines changed: 87 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GT__;
4141
import static com.oracle.graal.python.nodes.SpecialMethodNames.__LE__;
4242
import static com.oracle.graal.python.nodes.SpecialMethodNames.__LT__;
43+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__SETITEM__;
4344
import static com.oracle.graal.python.runtime.exception.PythonErrorType.IndexError;
4445
import static com.oracle.graal.python.runtime.exception.PythonErrorType.MemoryError;
4546
import static com.oracle.graal.python.runtime.exception.PythonErrorType.OverflowError;
@@ -62,6 +63,11 @@
6263
import com.oracle.graal.python.PythonLanguage;
6364
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
6465
import com.oracle.graal.python.builtins.modules.SysModuleBuiltins;
66+
import com.oracle.graal.python.builtins.objects.array.PArray;
67+
import com.oracle.graal.python.builtins.objects.bytes.BytesNodes;
68+
import com.oracle.graal.python.builtins.objects.bytes.PByteArray;
69+
import com.oracle.graal.python.builtins.objects.bytes.PBytes;
70+
import com.oracle.graal.python.builtins.objects.bytes.PBytesLike;
6571
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes;
6672
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.PCallCapiFunction;
6773
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.ToSulongNode;
@@ -1416,6 +1422,52 @@ protected static boolean isBasicSequenceStorage(Object o) {
14161422
}
14171423
}
14181424

1425+
@ImportStatic(PGuards.class)
1426+
public abstract static class BytesMemcpyNode extends PNodeWithContext {
1427+
1428+
public abstract void execute(VirtualFrame frame, Object dest, int destOffset, byte[] src, int srcOffset, int len);
1429+
1430+
protected static boolean isByteSequenceStorage(PByteArray bytes) {
1431+
return bytes.getSequenceStorage() instanceof ByteSequenceStorage;
1432+
}
1433+
1434+
protected static boolean isSimple(Object bytes) {
1435+
return bytes instanceof PByteArray && isByteSequenceStorage((PByteArray) bytes);
1436+
}
1437+
1438+
@Specialization(guards = "isByteSequenceStorage(dest)")
1439+
void doBytes(PByteArray dest, int destOffset, byte[] src, int srcOffset, int len,
1440+
@Cached SequenceStorageNodes.GetInternalArrayNode internalArray,
1441+
@Cached ConditionProfile profile) {
1442+
if (profile.profile(len > 0)) {
1443+
byte[] internal = (byte[]) internalArray.execute(dest.getSequenceStorage());
1444+
PythonUtils.arraycopy(src, srcOffset, internal, destOffset, len);
1445+
}
1446+
}
1447+
1448+
@Specialization
1449+
void doBytes(PArray dest, int destOffset, byte[] src, int srcOffset, int len,
1450+
@Cached ConditionProfile profile) {
1451+
if (profile.profile(len > 0)) {
1452+
PythonUtils.arraycopy(src, srcOffset, dest.getBuffer(), destOffset, len);
1453+
}
1454+
}
1455+
1456+
@Specialization(guards = {"!isSimple(dest)", "!isArray(dest)"}, limit = "2")
1457+
void doGeneric(VirtualFrame frame, Object dest, int destOffset, byte[] src, int srcOffset, int len,
1458+
@Cached PythonObjectFactory factory,
1459+
@CachedLibrary("dest") PythonObjectLibrary lib) {
1460+
PSlice slice = factory.createIntSlice(destOffset, destOffset + len, 1);
1461+
PBytes bytes;
1462+
if (src.length != len) {
1463+
bytes = factory.createBytes(Arrays.copyOfRange(src, srcOffset, srcOffset + len));
1464+
} else {
1465+
bytes = factory.createBytes(src);
1466+
}
1467+
lib.lookupAndCallRegularMethod(dest, frame, __SETITEM__, slice, bytes);
1468+
}
1469+
}
1470+
14191471
@GenerateUncached
14201472
@ImportStatic(SequenceStorageBaseNode.class)
14211473
abstract static class SetStorageSliceNode extends Node {
@@ -2086,9 +2138,37 @@ public static CmpNode createEq() {
20862138
}
20872139

20882140
/**
2089-
* Use this node to get the internal byte array of the storage (if possible). It will avoid
2090-
* copying any data but this also means that the returned byte array may be larger than the
2091-
* number of actual elements. So, you must also consider the sequence storage's size.
2141+
* Will try to get the internal byte[]. Otherwise, it will get a copy. Please note that the
2142+
* actual length of the storage and the internal storage might differ.
2143+
*/
2144+
public abstract static class GetInternalBytesNode extends PNodeWithContext {
2145+
2146+
public abstract byte[] execute(Object bytes);
2147+
2148+
protected static boolean isByteSequenceStorage(PBytesLike bytes) {
2149+
return bytes.getSequenceStorage() instanceof ByteSequenceStorage;
2150+
}
2151+
2152+
protected static boolean isSimple(Object bytes) {
2153+
return bytes instanceof PBytesLike && isByteSequenceStorage((PBytesLike) bytes);
2154+
}
2155+
2156+
@Specialization(guards = "isByteSequenceStorage(bytes)")
2157+
byte[] doBytes(PBytesLike bytes,
2158+
@Cached SequenceStorageNodes.GetInternalArrayNode internalArray) {
2159+
return (byte[]) internalArray.execute(bytes.getSequenceStorage());
2160+
}
2161+
2162+
@Specialization(guards = "!isSimple(bytes)")
2163+
byte[] doGeneric(Object bytes,
2164+
@Cached BytesNodes.ToBytesNode toBytesNode) {
2165+
return toBytesNode.execute(bytes);
2166+
}
2167+
}
2168+
2169+
/**
2170+
* Use this node to get the internal byte array of the storage (if possible) to avoid copying.
2171+
* Otherwise, it will create a copy with the exact size of the stored data.
20922172
*/
20932173
@GenerateUncached
20942174
@ImportStatic(SequenceStorageBaseNode.class)
@@ -2983,12 +3063,7 @@ public GeneralizationNode create() {
29833063
}
29843064
};
29853065

2986-
public static final Supplier<GeneralizationNode> CACHED_SUPPLIER = new Supplier<GeneralizationNode>() {
2987-
@Override
2988-
public GeneralizationNode get() {
2989-
return new ByteArrayGeneralizationNode();
2990-
}
2991-
};
3066+
public static final Supplier<GeneralizationNode> CACHED_SUPPLIER = () -> new ByteArrayGeneralizationNode();
29923067

29933068
@Override
29943069
public SequenceStorage execute(SequenceStorage toGeneralize, @SuppressWarnings("unused") Object indicationValue) {
@@ -3148,10 +3223,7 @@ protected static boolean isFallbackCase(SequenceStorage s, Object value, IsAssig
31483223
(value instanceof Byte || value instanceof Integer || value instanceof Long)) {
31493224
return false;
31503225
}
3151-
if (value instanceof SequenceStorage && isAssignCompatibleNode.execute(s, (SequenceStorage) value)) {
3152-
return false;
3153-
}
3154-
return true;
3226+
return !(value instanceof SequenceStorage) || !isAssignCompatibleNode.execute(s, (SequenceStorage) value);
31553227
}
31563228

31573229
public static ListGeneralizationNode create() {
@@ -3751,8 +3823,7 @@ static void singleStep(SequenceStorage store, SliceInfo sinfo,
37513823
@Cached ConditionProfile shortCircuitProfile,
37523824
@Cached LenNode selfLenNode,
37533825
@Cached SetLenNode setLenNode,
3754-
@Cached MemMoveNode memove,
3755-
@Cached @SuppressWarnings("unused") IsDataTypeCompatibleNode isDataTypeCompatibleNode) {
3826+
@Cached MemMoveNode memove) {
37563827
int length = selfLenNode.execute(store);
37573828
int sliceLength = sinfo.sliceLength;
37583829

@@ -3792,8 +3863,7 @@ static void multipleSteps(SequenceStorage store, SliceInfo sinfo,
37923863
@Cached EnsureCapacityNode ensureCapacityNode,
37933864
@Cached LenNode selfLenNode,
37943865
@Cached SetLenNode setLenNode,
3795-
@Cached MemMoveNode memove,
3796-
@Cached @SuppressWarnings("unused") IsDataTypeCompatibleNode isDataTypeCompatibleNode) {
3866+
@Cached MemMoveNode memove) {
37973867
multipleSteps(store, sinfo, selfLenNode, setLenNode, ensureCapacityNode, memove);
37983868
}
37993869

0 commit comments

Comments
 (0)