Skip to content

Commit ef1b8e7

Browse files
committed
[GR-62318] Fix PyObject_Bytes specialization consistency
PullRequest: graalpython/3692
2 parents 471fab3 + ae7f983 commit ef1b8e7

File tree

3 files changed

+46
-74
lines changed

3 files changed

+46
-74
lines changed

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

Lines changed: 9 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,11 @@
5353
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyObjectTransfer;
5454
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.Py_ssize_t;
5555
import static com.oracle.graal.python.builtins.objects.cext.structs.CFields.PyVarObject__ob_size;
56-
import static com.oracle.graal.python.nodes.ErrorMessages.CANNOT_CONVERT_P_OBJ_TO_S;
57-
import static com.oracle.graal.python.nodes.SpecialMethodNames.T___ITER__;
5856

5957
import java.util.Arrays;
6058

6159
import com.oracle.graal.python.PythonLanguage;
6260
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
63-
import com.oracle.graal.python.builtins.modules.BuiltinConstructors.BytesNode;
6461
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiBinaryBuiltinNode;
6562
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiBuiltin;
6663
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiCallPath;
@@ -88,13 +85,10 @@
8885
import com.oracle.graal.python.builtins.objects.str.StringBuiltins.ModNode;
8986
import com.oracle.graal.python.lib.PyBytesCheckNode;
9087
import com.oracle.graal.python.lib.PyNumberAsSizeNode;
91-
import com.oracle.graal.python.lib.PyObjectLookupAttr;
9288
import com.oracle.graal.python.lib.PyObjectSizeNode;
9389
import com.oracle.graal.python.nodes.ErrorMessages;
94-
import com.oracle.graal.python.nodes.PGuards;
9590
import com.oracle.graal.python.nodes.PRaiseNode;
9691
import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
97-
import com.oracle.graal.python.nodes.object.GetClassNode;
9892
import com.oracle.graal.python.nodes.object.GetClassNode.GetPythonObjectClassNode;
9993
import com.oracle.graal.python.nodes.util.CastToByteNode;
10094
import com.oracle.graal.python.runtime.exception.PythonErrorType;
@@ -177,33 +171,17 @@ static Object fromFormat(TruffleString fmt, Object args,
177171

178172
@CApiBuiltin(ret = PyObjectTransfer, args = {PyObject}, call = Direct)
179173
abstract static class PyBytes_FromObject extends CApiUnaryBuiltinNode {
180-
@Specialization
181-
static Object fromObject(Object obj,
182-
@Bind("this") Node inliningTarget,
183-
@Cached GetClassNode getClassNode,
184-
@Cached IsSubtypeNode isSubtypeNode,
185-
@Cached BytesNode bytesNode,
186-
@Cached PyObjectLookupAttr lookupAttrNode,
187-
@Cached PRaiseNode raiseNode) {
188-
if (PGuards.isPBytes(obj)) {
189-
return obj;
190-
} else {
191-
Object klass = getClassNode.execute(inliningTarget, obj);
192-
if (isSubtypeNode.execute(klass, PythonBuiltinClassType.PBytes)) {
193-
return obj;
194-
} else if (isAcceptedSubtype(inliningTarget, obj, klass, isSubtypeNode, lookupAttrNode)) {
195-
return bytesNode.execute(null, PythonBuiltinClassType.PBytes, obj, PNone.NO_VALUE, PNone.NO_VALUE);
196-
} else {
197-
throw raiseNode.raise(inliningTarget, TypeError, CANNOT_CONVERT_P_OBJ_TO_S, obj, "bytes");
198-
}
199-
}
174+
@Specialization(guards = "isBuiltinBytes(bytes)")
175+
static Object bytes(PBytes bytes) {
176+
return bytes;
200177
}
201178

202-
private static boolean isAcceptedSubtype(Node inliningTarget, Object obj, Object klass, IsSubtypeNode isSubtypeNode, PyObjectLookupAttr lookupAttrNode) {
203-
return isSubtypeNode.execute(klass, PythonBuiltinClassType.PList) ||
204-
isSubtypeNode.execute(klass, PythonBuiltinClassType.PTuple) ||
205-
isSubtypeNode.execute(klass, PythonBuiltinClassType.PMemoryView) ||
206-
(!isSubtypeNode.execute(klass, PythonBuiltinClassType.PString) && lookupAttrNode.execute(null, inliningTarget, obj, T___ITER__) != PNone.NO_VALUE);
179+
@Fallback
180+
static Object fromObject(Object obj,
181+
@Bind("this") Node inliningTarget,
182+
@Cached BytesNodes.BytesFromObject fromObject) {
183+
byte[] bytes = fromObject.execute(null, obj);
184+
return PFactory.createBytes(PythonLanguage.get(inliningTarget), bytes);
207185
}
208186
}
209187

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

Lines changed: 34 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
package com.oracle.graal.python.builtins.modules.cext;
4242

4343
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.NotImplementedError;
44+
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.TypeError;
4445
import static com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiCallPath.Direct;
4546
import static com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiCallPath.Ignored;
4647
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.ConstCharPtrAsTruffleString;
@@ -66,7 +67,6 @@
6667

6768
import com.oracle.graal.python.PythonLanguage;
6869
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
69-
import com.oracle.graal.python.builtins.modules.BuiltinConstructors.BytesNode;
7070
import com.oracle.graal.python.builtins.modules.BuiltinFunctions.FormatNode;
7171
import com.oracle.graal.python.builtins.modules.BuiltinFunctions.IsInstanceNode;
7272
import com.oracle.graal.python.builtins.modules.BuiltinFunctions.IsSubClassNode;
@@ -79,11 +79,11 @@
7979
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiUnaryBuiltinNode;
8080
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CastArgsNode;
8181
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CastKwargsNode;
82-
import com.oracle.graal.python.builtins.modules.cext.PythonCextBytesBuiltins.PyBytes_FromObject;
8382
import com.oracle.graal.python.builtins.objects.PNone;
8483
import com.oracle.graal.python.builtins.objects.PNotImplemented;
84+
import com.oracle.graal.python.builtins.objects.bytes.BytesNodes;
8585
import com.oracle.graal.python.builtins.objects.bytes.BytesUtils;
86-
import com.oracle.graal.python.builtins.objects.bytes.PBytesLike;
86+
import com.oracle.graal.python.builtins.objects.bytes.PBytes;
8787
import com.oracle.graal.python.builtins.objects.cext.capi.CApiGuards;
8888
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.ResolvePointerNode;
8989
import com.oracle.graal.python.builtins.objects.cext.capi.PythonNativeWrapper;
@@ -104,7 +104,9 @@
104104
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltins.GetAttributeNode;
105105
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltins.SetattrNode;
106106
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
107+
import com.oracle.graal.python.builtins.objects.type.SpecialMethodSlot;
107108
import com.oracle.graal.python.builtins.objects.type.TypeNodes;
109+
import com.oracle.graal.python.lib.PyBytesCheckNode;
108110
import com.oracle.graal.python.lib.PyCallableCheckNode;
109111
import com.oracle.graal.python.lib.PyLongCheckNode;
110112
import com.oracle.graal.python.lib.PyObjectAsFileDescriptor;
@@ -116,7 +118,6 @@
116118
import com.oracle.graal.python.lib.PyObjectGetIter;
117119
import com.oracle.graal.python.lib.PyObjectHashNode;
118120
import com.oracle.graal.python.lib.PyObjectIsTrueNode;
119-
import com.oracle.graal.python.lib.PyObjectLookupAttr;
120121
import com.oracle.graal.python.lib.PyObjectLookupAttrO;
121122
import com.oracle.graal.python.lib.PyObjectReprAsObjectNode;
122123
import com.oracle.graal.python.lib.PyObjectSetItem;
@@ -127,7 +128,8 @@
127128
import com.oracle.graal.python.nodes.StringLiterals;
128129
import com.oracle.graal.python.nodes.argument.keywords.ExpandKeywordStarargsNode;
129130
import com.oracle.graal.python.nodes.call.CallNode;
130-
import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
131+
import com.oracle.graal.python.nodes.call.special.CallUnaryMethodNode;
132+
import com.oracle.graal.python.nodes.call.special.LookupSpecialMethodSlotNode;
131133
import com.oracle.graal.python.nodes.object.GetClassNode;
132134
import com.oracle.graal.python.nodes.object.GetOrCreateDictNode;
133135
import com.oracle.graal.python.nodes.util.CannotCastException;
@@ -147,13 +149,15 @@
147149
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
148150
import com.oracle.truffle.api.dsl.Bind;
149151
import com.oracle.truffle.api.dsl.Cached;
150-
import com.oracle.truffle.api.dsl.Cached.Exclusive;
152+
import com.oracle.truffle.api.dsl.Fallback;
153+
import com.oracle.truffle.api.dsl.ImportStatic;
151154
import com.oracle.truffle.api.dsl.Specialization;
152155
import com.oracle.truffle.api.interop.InteropException;
153156
import com.oracle.truffle.api.interop.InteropLibrary;
154157
import com.oracle.truffle.api.library.CachedLibrary;
155158
import com.oracle.truffle.api.nodes.Node;
156159
import com.oracle.truffle.api.profiles.InlinedBranchProfile;
160+
import com.oracle.truffle.api.profiles.InlinedConditionProfile;
157161
import com.oracle.truffle.api.strings.TruffleString;
158162

159163
public abstract class PythonCextObjectBuiltins {
@@ -503,40 +507,13 @@ static int isTrue(Object obj,
503507
}
504508

505509
@CApiBuiltin(ret = PyObjectTransfer, args = {PyObject}, call = Direct)
510+
@ImportStatic(SpecialMethodSlot.class)
506511
abstract static class PyObject_Bytes extends CApiUnaryBuiltinNode {
507-
@Specialization
508-
static Object bytes(PBytesLike bytes) {
509-
return bytes;
510-
}
511-
512-
@Specialization(guards = {"!isBytes(bytes)", "isBytesSubtype(inliningTarget, bytes, getClassNode, isSubtypeNode)"}, limit = "1")
513-
static Object bytes(Object bytes,
514-
@SuppressWarnings("unused") @Bind("this") Node inliningTarget,
515-
@SuppressWarnings("unused") @Exclusive @Cached GetClassNode getClassNode,
516-
@SuppressWarnings("unused") @Exclusive @Cached IsSubtypeNode isSubtypeNode) {
512+
@Specialization(guards = "isBuiltinBytes(bytes)")
513+
static Object bytes(PBytes bytes) {
517514
return bytes;
518515
}
519516

520-
@Specialization(guards = {"!isBytes(obj)", "!isBytesSubtype(this, obj, getClassNode, isSubtypeNode)", "!isNoValue(obj)", "hasBytes(inliningTarget, obj, lookupAttrNode)"}, limit = "1")
521-
static Object bytes(Object obj,
522-
@SuppressWarnings("unused") @Bind("this") Node inliningTarget,
523-
@SuppressWarnings("unused") @Exclusive @Cached GetClassNode getClassNode,
524-
@SuppressWarnings("unused") @Exclusive @Cached IsSubtypeNode isSubtypeNode,
525-
@SuppressWarnings("unused") @Exclusive @Cached PyObjectLookupAttr lookupAttrNode,
526-
@Cached BytesNode bytesNode) {
527-
return bytesNode.execute(null, PythonBuiltinClassType.PBytes, obj, PNone.NO_VALUE, PNone.NO_VALUE);
528-
}
529-
530-
@Specialization(guards = {"!isBytes(obj)", "!isBytesSubtype(this, obj, getClassNode, isSubtypeNode)", "!isNoValue(obj)", "!hasBytes(inliningTarget, obj, lookupAttrNode)"}, limit = "1")
531-
static Object bytes(Object obj,
532-
@SuppressWarnings("unused") @Bind("this") Node inliningTarget,
533-
@SuppressWarnings("unused") @Exclusive @Cached GetClassNode getClassNode,
534-
@SuppressWarnings("unused") @Exclusive @Cached IsSubtypeNode isSubtypeNode,
535-
@SuppressWarnings("unused") @Exclusive @Cached PyObjectLookupAttr lookupAttrNode,
536-
@Cached PyBytes_FromObject fromObjectNode) {
537-
return fromObjectNode.execute(obj);
538-
}
539-
540517
@Specialization(guards = "isNoValue(obj)")
541518
static Object bytesNoValue(@SuppressWarnings("unused") Object obj,
542519
@Bind PythonLanguage language) {
@@ -547,12 +524,27 @@ static Object bytesNoValue(@SuppressWarnings("unused") Object obj,
547524
return PFactory.createBytes(language, BytesUtils.NULL_STRING);
548525
}
549526

550-
protected static boolean hasBytes(Node inliningTarget, Object obj, PyObjectLookupAttr lookupAttrNode) {
551-
return lookupAttrNode.execute(null, inliningTarget, obj, T___BYTES__) != PNone.NO_VALUE;
552-
}
553-
554-
protected static boolean isBytesSubtype(Node inliningTarget, Object obj, GetClassNode getClassNode, IsSubtypeNode isSubtypeNode) {
555-
return isSubtypeNode.execute(getClassNode.execute(inliningTarget, obj), PythonBuiltinClassType.PBytes);
527+
@Fallback
528+
static Object doGeneric(Object obj,
529+
@Bind("this") Node inliningTarget,
530+
@Cached GetClassNode getClassNode,
531+
@Cached InlinedConditionProfile hasBytes,
532+
@Cached("create(Bytes)") LookupSpecialMethodSlotNode lookupBytes,
533+
@Cached CallUnaryMethodNode callBytes,
534+
@Cached PyBytesCheckNode check,
535+
@Cached BytesNodes.BytesFromObject fromObject,
536+
@Cached PRaiseNode raiseNode) {
537+
Object bytesMethod = lookupBytes.execute(null, getClassNode.execute(inliningTarget, obj), obj);
538+
if (hasBytes.profile(inliningTarget, bytesMethod != PNone.NO_VALUE)) {
539+
Object bytes = callBytes.executeObject(null, bytesMethod, obj);
540+
if (check.execute(inliningTarget, bytes)) {
541+
return bytes;
542+
} else {
543+
throw raiseNode.raise(inliningTarget, TypeError, ErrorMessages.RETURNED_NONBYTES, T___BYTES__, bytes);
544+
}
545+
}
546+
byte[] bytes = fromObject.execute(null, obj);
547+
return PFactory.createBytes(PythonLanguage.get(inliningTarget), bytes);
556548
}
557549
}
558550

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
import com.oracle.graal.python.lib.PyNumberAsSizeNode;
8484
import com.oracle.graal.python.lib.PyOSFSPathNode;
8585
import com.oracle.graal.python.lib.PyObjectGetIter;
86+
import com.oracle.graal.python.lib.PyUnicodeCheckNode;
8687
import com.oracle.graal.python.nodes.ErrorMessages;
8788
import com.oracle.graal.python.nodes.PGuards;
8889
import com.oracle.graal.python.nodes.PNodeWithContext;
@@ -560,6 +561,7 @@ static byte[] doGeneric(VirtualFrame frame, Object object,
560561
@CachedLibrary(limit = "3") PythonBufferAccessLibrary bufferLib,
561562
@Cached BytesNodes.IterableToByteNode iterableToByteNode,
562563
@Cached IsBuiltinObjectProfile errorProfile,
564+
@Cached PyUnicodeCheckNode unicodeCheckNode,
563565
@Cached PRaiseNode raiseNode) {
564566
if (bufferAcquireLib.hasBuffer(object)) {
565567
// TODO PyBUF_FULL_RO
@@ -570,7 +572,7 @@ static byte[] doGeneric(VirtualFrame frame, Object object,
570572
bufferLib.release(buffer, frame, indirectCallData);
571573
}
572574
}
573-
if (!PGuards.isString(object)) {
575+
if (!unicodeCheckNode.execute(inliningTarget, object)) {
574576
try {
575577
return iterableToByteNode.execute(frame, object);
576578
} catch (PException e) {

0 commit comments

Comments
 (0)