Skip to content

Commit cb8e767

Browse files
committed
Accept long values for casting pointers
1 parent 6df81f0 commit cb8e767

File tree

2 files changed

+95
-68
lines changed

2 files changed

+95
-68
lines changed

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

Lines changed: 90 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@
168168
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryClinicBuiltinNode;
169169
import com.oracle.graal.python.nodes.function.builtins.clinic.ArgumentClinicProvider;
170170
import com.oracle.graal.python.nodes.object.BuiltinClassProfiles.IsBuiltinObjectProfile;
171-
import com.oracle.graal.python.nodes.object.GetClassNode;
171+
import com.oracle.graal.python.nodes.object.InlinedGetClassNode;
172172
import com.oracle.graal.python.nodes.util.CastToJavaStringNode;
173173
import com.oracle.graal.python.nodes.util.CastToTruffleStringNode;
174174
import com.oracle.graal.python.runtime.ExecutionContext.IndirectCallContext;
@@ -554,13 +554,14 @@ Object pointer(VirtualFrame frame, Object arg,
554554
@Cached HashingStorageGetItem getItem,
555555
@Cached PointerTypeNode callPOINTER,
556556
@Cached CallNode callNode,
557-
@Cached GetClassNode getClassNode) {
557+
@Bind("this") Node inliningTarget,
558+
@Cached InlinedGetClassNode getClassNode) {
558559
CtypesThreadState ctypes = CtypesThreadState.get(getContext(), getLanguage());
559-
Object typ = getItem.execute(frame, ctypes.ptrtype_cache, getClassNode.execute(arg));
560+
Object typ = getItem.execute(frame, ctypes.ptrtype_cache, getClassNode.execute(inliningTarget, arg));
560561
if (typ != null) {
561562
return callNode.execute(frame, typ, arg);
562563
}
563-
typ = callPOINTER.execute(frame, getClassNode.execute(arg));
564+
typ = callPOINTER.execute(frame, getClassNode.execute(inliningTarget, arg));
564565
return callNode.execute(frame, typ, arg);
565566
}
566567
}
@@ -1039,10 +1040,12 @@ protected ArgumentClinicProvider getArgumentClinic() {
10391040

10401041
@Specialization
10411042
Object doit(CDataObject obj, int offset,
1043+
@Bind("this") Node inliningTarget,
1044+
@Shared @Cached InlinedGetClassNode getClassNode,
10421045
@Cached PyTypeCheck pyTypeCheck,
10431046
@Cached PyObjectStgDictNode pyObjectStgDictNode) {
10441047
if (!pyTypeCheck.isCDataObject(obj)) {
1045-
return error(null, obj, offset);
1048+
return error(null, obj, offset, inliningTarget, getClassNode);
10461049
}
10471050
FFIType ffiType = pyObjectStgDictNode.execute(obj).ffi_type_pointer;
10481051
PyCArgObject parg = factory().createCArgObject();
@@ -1062,8 +1065,10 @@ Object doit(CDataObject obj, int offset,
10621065

10631066
@SuppressWarnings("unused")
10641067
@Fallback
1065-
Object error(VirtualFrame frame, Object obj, Object off) {
1066-
Object clazz = GetClassNode.getUncached().execute(obj);
1068+
Object error(VirtualFrame frame, Object obj, Object off,
1069+
@Bind("this") Node inliningTarget,
1070+
@Shared @Cached InlinedGetClassNode getClassNode) {
1071+
Object clazz = getClassNode.execute(inliningTarget, obj);
10671072
TruffleString name = GetNameNode.getUncached().execute(clazz);
10681073
throw raise(TypeError, BYREF_ARGUMENT_MUST_BE_A_CTYPES_INSTANCE_NOT_S, name);
10691074
}
@@ -1733,43 +1738,96 @@ Object execute(Object[] arguments,
17331738
}
17341739
}
17351740

1736-
@ImportStatic(PGuards.class)
17371741
@GenerateUncached
1738-
protected abstract static class CastFunctionNode extends Node {
1742+
abstract static class FailedCastCheckNode extends Node {
1743+
abstract void execute(Object arg);
1744+
1745+
@Specialization
1746+
static void raiseError(Object arg,
1747+
@Cached PRaiseNode raiseNode,
1748+
@Cached IsTypeNode isTypeNode,
1749+
@Bind("this") Node inliningTarget,
1750+
@Cached InlinedGetClassNode getClassNode,
1751+
@Cached GetNameNode getNameNode) {
1752+
Object clazz = isTypeNode.execute(arg) ? arg : getClassNode.execute(inliningTarget, arg);
1753+
throw raiseNode.raise(TypeError, CAST_ARGUMENT_2_MUST_BE_A_POINTER_TYPE_NOT_S, getNameNode.execute(clazz));
1754+
}
1755+
}
1756+
1757+
// cast_check_pointertype
1758+
@GenerateUncached
1759+
abstract static class CastCheckPtrTypeNode extends Node {
17391760

17401761
private static final char[] sPzUZXO = "sPzUZXO".toCharArray();
17411762

1742-
abstract Object execute(Object ptr, Object src, Object ctype);
1763+
abstract void execute(Object arg);
17431764

1744-
@Specialization
1745-
static Object cast(PythonNativeVoidPtr ptr, @SuppressWarnings("unused") PythonNativeVoidPtr src, Object ctype,
1746-
@Cached PyTypeCheck pyTypeCheck,
1747-
@Cached CallNode callNode,
1748-
@Cached PRaiseNode raiseNode,
1765+
protected static boolean isPtrTypeObject(Object arg, PyTypeCheck pyTypeCheck) {
1766+
return pyTypeCheck.isPyCPointerTypeObject(arg) || pyTypeCheck.isPyCFuncPtrTypeObject(arg);
1767+
}
1768+
1769+
@Specialization(guards = "isPtrTypeObject(arg, pyTypeCheck)")
1770+
static void fastCheck(@SuppressWarnings("unused") Object arg,
1771+
@SuppressWarnings("unused") @Shared @Cached PyTypeCheck pyTypeCheck) {
1772+
}
1773+
1774+
@Specialization(replaces = {"fastCheck"})
1775+
static void fullcheck(Object arg,
1776+
@Shared @Cached PyTypeCheck pyTypeCheck,
17491777
@Cached PyTypeStgDictNode pyTypeStgDictNode,
1750-
@Cached IsTypeNode isTypeNode,
1751-
@Cached GetClassNode getClassNode,
1752-
@Cached GetNameNode getNameNode,
1778+
@Cached FailedCastCheckNode failedCastCheckNode,
17531779
@Cached TruffleString.CodePointAtIndexNode codePointAtIndexNode) {
1754-
cast_check_pointertype(ctype, raiseNode, pyTypeCheck, pyTypeStgDictNode, isTypeNode, getClassNode, getNameNode, codePointAtIndexNode);
1780+
if (isPtrTypeObject(arg, pyTypeCheck)) {
1781+
return;
1782+
}
1783+
StgDictObject dict = pyTypeStgDictNode.execute(arg);
1784+
if (dict != null && dict.proto != null) {
1785+
if (PGuards.isTruffleString(dict.proto)) {
1786+
int code = codePointAtIndexNode.execute((TruffleString) dict.proto, 0, TS_ENCODING);
1787+
if (strchr(sPzUZXO, code)) {
1788+
/* simple pointer types, c_void_p, c_wchar_p, BSTR, ... */
1789+
return;
1790+
}
1791+
}
1792+
}
1793+
failedCastCheckNode.execute(arg);
1794+
}
1795+
}
1796+
1797+
@ImportStatic(PGuards.class)
1798+
@GenerateUncached
1799+
protected abstract static class CastFunctionNode extends Node {
1800+
1801+
abstract Object execute(Object ptr, Object src, Object ctype);
1802+
1803+
@Specialization
1804+
static Object l(long ptr, @SuppressWarnings("unused") long src, Object ctype,
1805+
@Shared @Cached CastCheckPtrTypeNode castCheckPtrTypeNode,
1806+
@Shared @Cached CallNode callNode) {
1807+
castCheckPtrTypeNode.execute(ctype);
1808+
CDataObject result = (CDataObject) callNode.execute(ctype);
1809+
result.b_ptr = PtrValue.nativePointer(ptr);
1810+
return result;
1811+
}
1812+
1813+
@Specialization
1814+
static Object nativeptr(PythonNativeVoidPtr ptr, @SuppressWarnings("unused") PythonNativeVoidPtr src, Object ctype,
1815+
@Shared @Cached CastCheckPtrTypeNode castCheckPtrTypeNode,
1816+
@Shared @Cached CallNode callNode) {
1817+
castCheckPtrTypeNode.execute(ctype);
17551818
CDataObject result = (CDataObject) callNode.execute(ctype);
17561819
result.b_ptr = PtrValue.nativePointer(ptr.getPointerObject());
17571820
return result;
17581821
}
17591822

17601823
@Specialization
1761-
static Object cast(CDataObject ptr, CDataObject src, Object ctype,
1824+
static Object cdata(CDataObject ptr, CDataObject src, Object ctype,
17621825
@Cached HashingStorageSetItem setItem,
17631826
@Cached PyTypeCheck pyTypeCheck,
17641827
@Cached PythonObjectFactory factory,
1765-
@Cached CallNode callNode,
1766-
@Cached PRaiseNode raiseNode,
1767-
@Cached PyTypeStgDictNode pyTypeStgDictNode,
1768-
@Cached IsTypeNode isTypeNode,
1769-
@Cached GetClassNode getClassNode,
1770-
@Cached GetNameNode getNameNode,
1771-
@Cached TruffleString.CodePointAtIndexNode codePointAtIndexNode) {
1772-
cast_check_pointertype(ctype, raiseNode, pyTypeCheck, pyTypeStgDictNode, isTypeNode, getClassNode, getNameNode, codePointAtIndexNode);
1828+
@Shared @Cached CallNode callNode,
1829+
@Shared @Cached CastCheckPtrTypeNode castCheckPtrTypeNode) {
1830+
castCheckPtrTypeNode.execute(ctype);
17731831
CDataObject result = (CDataObject) callNode.execute(ctype);
17741832

17751833
/*
@@ -1804,16 +1862,10 @@ static Object cast(CDataObject ptr, CDataObject src, Object ctype,
18041862
}
18051863

18061864
@Specialization(guards = "!isCDataObject(src)")
1807-
static Object cast(PtrValue ptr, @SuppressWarnings("unused") Object src, Object ctype,
1808-
@Cached PyTypeCheck pyTypeCheck,
1809-
@Cached CallNode callNode,
1810-
@Cached PRaiseNode raiseNode,
1811-
@Cached PyTypeStgDictNode pyTypeStgDictNode,
1812-
@Cached IsTypeNode isTypeNode,
1813-
@Cached GetClassNode getClassNode,
1814-
@Cached GetNameNode getNameNode,
1815-
@Cached TruffleString.CodePointAtIndexNode codePointAtIndexNode) {
1816-
cast_check_pointertype(ctype, raiseNode, pyTypeCheck, pyTypeStgDictNode, isTypeNode, getClassNode, getNameNode, codePointAtIndexNode);
1865+
static Object ptr(PtrValue ptr, @SuppressWarnings("unused") Object src, Object ctype,
1866+
@Shared @Cached CastCheckPtrTypeNode castCheckPtrTypeNode,
1867+
@Shared @Cached CallNode callNode) {
1868+
castCheckPtrTypeNode.execute(ctype);
18171869
CDataObject result = (CDataObject) callNode.execute(ctype);
18181870

18191871
/* Should we assert that result is a pointer type? */
@@ -1822,33 +1874,6 @@ static Object cast(PtrValue ptr, @SuppressWarnings("unused") Object src, Object
18221874
return result;
18231875
}
18241876

1825-
static void cast_check_pointertype(Object arg,
1826-
PRaiseNode raiseNode,
1827-
PyTypeCheck pyTypeCheck,
1828-
PyTypeStgDictNode pyTypeStgDictNode,
1829-
IsTypeNode isTypeNode,
1830-
GetClassNode getClassNode,
1831-
GetNameNode getNameNode,
1832-
TruffleString.CodePointAtIndexNode codePointAtIndexNode) {
1833-
if (pyTypeCheck.isPyCPointerTypeObject(arg)) {
1834-
return;
1835-
}
1836-
if (pyTypeCheck.isPyCFuncPtrTypeObject(arg)) {
1837-
return;
1838-
}
1839-
StgDictObject dict = pyTypeStgDictNode.execute(arg);
1840-
if (dict != null && dict.proto != null) {
1841-
if (PGuards.isTruffleString(dict.proto)) {
1842-
int code = codePointAtIndexNode.execute((TruffleString) dict.proto, 0, TS_ENCODING);
1843-
if (strchr(sPzUZXO, code)) {
1844-
/* simple pointer types, c_void_p, c_wchar_p, BSTR, ... */
1845-
return;
1846-
}
1847-
}
1848-
}
1849-
Object clazz = isTypeNode.execute(arg) ? arg : getClassNode.execute(arg);
1850-
throw raiseNode.raise(TypeError, CAST_ARGUMENT_2_MUST_BE_A_POINTER_TYPE_NOT_S, getNameNode.execute(clazz));
1851-
}
18521877
}
18531878

18541879
@ExportLibrary(InteropLibrary.class)

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,11 @@
6363
import com.oracle.graal.python.nodes.PNodeWithContext;
6464
import com.oracle.graal.python.nodes.PRaiseNode;
6565
import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
66-
import com.oracle.graal.python.nodes.object.GetClassNode;
66+
import com.oracle.graal.python.nodes.object.InlinedGetClassNode;
6767
import com.oracle.graal.python.runtime.PythonContext;
6868
import com.oracle.truffle.api.CompilerDirectives;
6969
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
70+
import com.oracle.truffle.api.dsl.Bind;
7071
import com.oracle.truffle.api.dsl.Cached;
7172
import com.oracle.truffle.api.dsl.Cached.Shared;
7273
import com.oracle.truffle.api.dsl.GenerateUncached;
@@ -151,9 +152,10 @@ protected final boolean isPyCStructTypeObject(Object obj) {
151152

152153
@Specialization
153154
static boolean checkType(Object receiver, Object type,
154-
@Cached GetClassNode getClassNode,
155+
@Bind("this") Node inliningTarget,
156+
@Cached InlinedGetClassNode getClassNode,
155157
@Cached IsSubtypeNode isSubtypeNode) {
156-
Object clazz = getClassNode.execute(receiver);
158+
Object clazz = getClassNode.execute(inliningTarget, receiver);
157159
// IsSameTypeNode.execute(clazz, type) is done within IsSubtypeNode
158160
return isSubtypeNode.execute(clazz, type);
159161
}

0 commit comments

Comments
 (0)