Skip to content

Commit 3f9c1b4

Browse files
committed
[GR-9246] Various C API fixes around primitive types and pointers.
PullRequest: graalpython/201
2 parents 6b2ef5b + c202f84 commit 3f9c1b4

File tree

12 files changed

+326
-125
lines changed

12 files changed

+326
-125
lines changed

graalpython/com.oracle.graal.python.cext/src/longobject.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,9 @@ PyObject * PyLong_FromSsize_t(Py_ssize_t n) {
8585
return PyLong_FromLongLong(n);
8686
}
8787

88-
UPCALL_ID(PyLong_FromLongLong);
88+
UPCALL_ID(PyLong_FromDouble);
8989
PyObject * PyLong_FromDouble(double n) {
90-
return UPCALL_CEXT_O(_jls_PyLong_FromLongLong, n, 1);
90+
return UPCALL_CEXT_O(_jls_PyLong_FromDouble, n);
9191
}
9292

9393
UPCALL_ID(ssize_t);
@@ -106,10 +106,13 @@ PyObject * PyLong_FromVoidPtr(void *p) {
106106
return PyLong_FromUnsignedLongLong((unsigned long long)(uintptr_t)p);
107107
#endif /* SIZEOF_VOID_P <= SIZEOF_LONG */
108108
}
109+
110+
UPCALL_ID(PyLong_AsVoidPtr);
109111
void * PyLong_AsVoidPtr(PyObject *obj){
110-
return (void *)PyLong_AsSsize_t(obj);
112+
return (void *)UPCALL_CEXT_PTR(_jls_PyLong_AsVoidPtr, native_to_java(obj));
111113
}
112114

115+
UPCALL_ID(PyLong_FromLongLong);
113116
PyObject * PyLong_FromLong(long n) {
114117
return UPCALL_CEXT_O(_jls_PyLong_FromLongLong, n, 1);
115118
}

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_long.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,38 @@ def compile_module(self, name):
239239
cmpfunc=unhandled_error_compare
240240
)
241241

242+
test_PyLong_FromVoidPtrAllocated = CPyExtFunction(
243+
lambda args: int,
244+
lambda: ((None,),),
245+
code="""PyObject* PyLong_FromVoidPtrAllocated(PyObject* none) {
246+
void* dummyPtr = malloc(sizeof(size_t));
247+
return (PyObject*)Py_TYPE(PyLong_FromVoidPtr(dummyPtr));
248+
}
249+
""",
250+
resultspec="O",
251+
argspec='O',
252+
arguments=["PyObject* none"],
253+
cmpfunc=unhandled_error_compare
254+
)
255+
256+
test_PyLong_AsVoidPtrAllocated = CPyExtFunction(
257+
lambda args: True,
258+
lambda: ((None,),),
259+
code="""PyObject* PyLong_AsVoidPtrAllocated(PyObject* none) {
260+
void* dummyPtr = malloc(sizeof(size_t));
261+
PyObject* obj = PyLong_FromVoidPtr(dummyPtr);
262+
void* unwrappedPtr = PyLong_AsVoidPtr(obj);
263+
PyObject* result = unwrappedPtr == dummyPtr ? Py_True : Py_False;
264+
free(dummyPtr);
265+
return result;
266+
}
267+
""",
268+
resultspec="O",
269+
argspec='O',
270+
arguments=["PyObject* none"],
271+
cmpfunc=unhandled_error_compare
272+
)
273+
242274
test_PyLong_Check = CPyExtFunction(
243275
lambda args: isinstance(args[0], int),
244276
lambda: (

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public enum PythonBuiltinClassType {
5959
PGenerator(com.oracle.graal.python.builtins.objects.generator.PGenerator.class, "generator"),
6060
PGeneratorFunction(com.oracle.graal.python.builtins.objects.function.PGeneratorFunction.class, "function"),
6161
PInt(com.oracle.graal.python.builtins.objects.ints.PInt.class, "int"),
62+
PythonNativeVoidPtr(com.oracle.graal.python.builtins.objects.cext.PythonNativeVoidPtr.class, "int"),
6263
PIntegerSequenceIterator(com.oracle.graal.python.builtins.objects.iterator.PIntegerSequenceIterator.class, "iterator"),
6364
PList(com.oracle.graal.python.builtins.objects.list.PList.class, "list"),
6465
PLongSequenceIterator(com.oracle.graal.python.builtins.objects.iterator.PLongSequenceIterator.class, "iterator"),

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

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@
6969
import com.oracle.graal.python.builtins.objects.bytes.PByteArray;
7070
import com.oracle.graal.python.builtins.objects.bytes.PBytes;
7171
import com.oracle.graal.python.builtins.objects.bytes.PIBytesLike;
72-
import com.oracle.graal.python.builtins.objects.common.SequenceNodes.LenNode;
7372
import com.oracle.graal.python.builtins.objects.common.SequenceNodes;
73+
import com.oracle.graal.python.builtins.objects.common.SequenceNodes.LenNode;
7474
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
7575
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.GetItemNode;
7676
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.ToByteArrayNode;
@@ -85,6 +85,7 @@
8585
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
8686
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
8787
import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes;
88+
import com.oracle.graal.python.nodes.util.CastToIndexNode;
8889
import com.oracle.graal.python.runtime.PythonCore;
8990
import com.oracle.graal.python.runtime.exception.PException;
9091
import com.oracle.graal.python.runtime.exception.PythonErrorType;
@@ -329,14 +330,10 @@ Object fstat(int fd,
329330
}
330331

331332
@Specialization
332-
Object fstatPInt(PInt fd,
333+
Object fstatPInt(Object fd,
334+
@Cached("createOverflow()") CastToIndexNode castToIntNode,
333335
@Cached("create()") FstatNode recursive) {
334-
return recursive.executeWith(fd.intValue());
335-
}
336-
337-
@Fallback
338-
Object doGeneric(Object o) {
339-
throw raise(TypeError, "an integer is required (got type %p)", o);
336+
return recursive.executeWith(castToIntNode.execute(fd));
340337
}
341338

342339
protected static StatNode createStatNode() {
@@ -775,9 +772,10 @@ Object writeStd(int fd, PByteArray data) {
775772
}
776773

777774
@Specialization
778-
Object writePInt(PInt fd, Object data,
775+
Object writePInt(Object fd, Object data,
776+
@Cached("createOverflow()") CastToIndexNode castToIntNode,
779777
@Cached("create()") WriteNode recursive) {
780-
return recursive.executeWith(fd.intValue(), data);
778+
return recursive.executeWith(castToIntNode.execute(fd), data);
781779
}
782780

783781
private byte[] getByteArray(PIBytesLike pByteArray) {
@@ -788,7 +786,7 @@ private byte[] getByteArray(PIBytesLike pByteArray) {
788786
return toByteArrayNode.execute(pByteArray.getSequenceStorage());
789787
}
790788

791-
protected WriteNode create() {
789+
public static WriteNode create() {
792790
return PosixModuleBuiltinsFactory.WriteNodeFactory.create(null);
793791
}
794792
}

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

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,11 @@
4040
*/
4141
package com.oracle.graal.python.builtins.modules;
4242

43+
import static com.oracle.graal.python.runtime.exception.PythonErrorType.OverflowError;
4344
import static com.oracle.graal.python.runtime.exception.PythonErrorType.SystemError;
4445
import static com.oracle.graal.python.runtime.exception.PythonErrorType.TypeError;
4546

47+
import java.math.BigInteger;
4648
import java.nio.ByteBuffer;
4749
import java.nio.CharBuffer;
4850
import java.nio.charset.CharacterCodingException;
@@ -60,6 +62,7 @@
6062
import com.oracle.graal.python.builtins.PythonBuiltins;
6163
import com.oracle.graal.python.builtins.modules.TruffleCextBuiltinsFactory.CheckFunctionResultNodeGen;
6264
import com.oracle.graal.python.builtins.modules.TruffleCextBuiltinsFactory.GetByteArrayNodeGen;
65+
import com.oracle.graal.python.builtins.modules.TruffleCextBuiltinsFactory.TrufflePInt_AsPrimitiveFactory;
6366
import com.oracle.graal.python.builtins.objects.PNone;
6467
import com.oracle.graal.python.builtins.objects.PythonAbstractObject;
6568
import com.oracle.graal.python.builtins.objects.bytes.BytesBuiltins;
@@ -84,6 +87,8 @@
8487
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonObjectNativeWrapper;
8588
import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass;
8689
import com.oracle.graal.python.builtins.objects.cext.PythonNativeNull;
90+
import com.oracle.graal.python.builtins.objects.cext.PythonNativeObject;
91+
import com.oracle.graal.python.builtins.objects.cext.PythonNativeVoidPtr;
8792
import com.oracle.graal.python.builtins.objects.cext.UnicodeObjectNodes.UnicodeAsWideCharNode;
8893
import com.oracle.graal.python.builtins.objects.code.PCode;
8994
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes;
@@ -836,6 +841,12 @@ protected static String getUTF32Name(int byteorder) {
836841
@GenerateNodeFactory
837842
abstract static class TrufflePInt_AsPrimitive extends NativeBuiltin {
838843

844+
public abstract Object executeWith(Object o, int signed, long targetTypeSize, String targetTypeName);
845+
846+
public abstract long executeLong(Object o, int signed, long targetTypeSize, String targetTypeName);
847+
848+
public abstract int executeInt(Object o, int signed, long targetTypeSize, String targetTypeName);
849+
839850
@Specialization(guards = "targetTypeSize == 4")
840851
int doInt4(int obj, @SuppressWarnings("unused") int signed, @SuppressWarnings("unused") long targetTypeSize, @SuppressWarnings("unused") String targetTypeName) {
841852
return obj;
@@ -1863,4 +1874,93 @@ Object createCache(TruffleObject ptrToResolveHandle) {
18631874
return new HandleCache(ptrToResolveHandle);
18641875
}
18651876
}
1877+
1878+
@Builtin(name = "PyLong_FromLongLong", fixedNumOfPositionalArgs = 2)
1879+
@GenerateNodeFactory
1880+
abstract static class PyLong_FromLongLong extends PythonBinaryBuiltinNode {
1881+
@Specialization(guards = "signed != 0")
1882+
Object doSignedInt(int n, @SuppressWarnings("unused") int signed,
1883+
@Cached("create()") CExtNodes.ToSulongNode toSulongNode) {
1884+
return toSulongNode.execute(n);
1885+
}
1886+
1887+
@Specialization(guards = "signed == 0")
1888+
Object doUnsignedInt(int n, @SuppressWarnings("unused") int signed,
1889+
@Cached("create()") CExtNodes.ToSulongNode toSulongNode) {
1890+
if (n < 0) {
1891+
return toSulongNode.execute(n & 0xFFFFFFFFL);
1892+
}
1893+
return toSulongNode.execute(n);
1894+
}
1895+
1896+
@Specialization(guards = "signed != 0")
1897+
Object doSignedLong(long n, @SuppressWarnings("unused") int signed,
1898+
@Cached("create()") CExtNodes.ToSulongNode toSulongNode) {
1899+
return toSulongNode.execute(n);
1900+
}
1901+
1902+
@Specialization(guards = {"signed == 0", "n >= 0"})
1903+
Object doUnsignedLongPositive(long n, @SuppressWarnings("unused") int signed,
1904+
@Cached("create()") CExtNodes.ToSulongNode toSulongNode) {
1905+
return toSulongNode.execute(n);
1906+
}
1907+
1908+
@Specialization(guards = {"signed == 0", "n < 0"})
1909+
Object doUnsignedLongNegative(long n, @SuppressWarnings("unused") int signed,
1910+
@Cached("create()") CExtNodes.ToSulongNode toSulongNode) {
1911+
return toSulongNode.execute(factory().createInt(convertToBigInteger(n)));
1912+
}
1913+
1914+
@TruffleBoundary
1915+
private static BigInteger convertToBigInteger(long n) {
1916+
return BigInteger.valueOf(n).add(BigInteger.ONE.shiftLeft(64));
1917+
}
1918+
1919+
@Specialization
1920+
Object doPointer(PythonNativeObject n, @SuppressWarnings("unused") int signed,
1921+
@Cached("create()") CExtNodes.ToSulongNode toSulongNode) {
1922+
return toSulongNode.execute(factory().createNativeVoidPtr((TruffleObject) n.object));
1923+
}
1924+
}
1925+
1926+
@Builtin(name = "PyLong_AsVoidPtr", fixedNumOfPositionalArgs = 1)
1927+
@GenerateNodeFactory
1928+
abstract static class PyLong_AsVoidPtr extends PythonUnaryBuiltinNode {
1929+
@Child private TrufflePInt_AsPrimitive asPrimitiveNode;
1930+
1931+
@Specialization
1932+
long doPointer(int n) {
1933+
return n;
1934+
}
1935+
1936+
@Specialization
1937+
long doPointer(long n) {
1938+
return n;
1939+
}
1940+
1941+
@Specialization
1942+
long doPointer(PInt n,
1943+
@Cached("create()") BranchProfile overflowProfile) {
1944+
try {
1945+
return n.longValueExact();
1946+
} catch (ArithmeticException e) {
1947+
overflowProfile.enter();
1948+
throw raise(OverflowError);
1949+
}
1950+
}
1951+
1952+
@Specialization
1953+
TruffleObject doPointer(PythonNativeVoidPtr n) {
1954+
return n.object;
1955+
}
1956+
1957+
@Fallback
1958+
long doGeneric(Object n) {
1959+
if (asPrimitiveNode == null) {
1960+
CompilerDirectives.transferToInterpreterAndInvalidate();
1961+
asPrimitiveNode = insert(TrufflePInt_AsPrimitiveFactory.create(null));
1962+
}
1963+
return asPrimitiveNode.executeLong(n, 0, Long.BYTES, "void*");
1964+
}
1965+
}
18661966
}

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

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.BoolNativeWrapper;
6363
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.ByteNativeWrapper;
6464
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.DoubleNativeWrapper;
65+
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.DynamicObjectNativeWrapper;
6566
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.IntNativeWrapper;
6667
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.LongNativeWrapper;
6768
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PrimitiveNativeWrapper;
@@ -265,20 +266,22 @@ public abstract static class ToSulongNode extends CExtBaseNode {
265266

266267
public abstract Object execute(Object obj);
267268

268-
/*
269-
* This is very sad. Only for Sulong, we cannot hand out java.lang.Strings, because then it
270-
* won't know what to do with them when they go native. So all places where Strings may be
271-
* passed from Python into C code need to wrap Strings into PStrings.
272-
*/
273269
@Specialization
274270
Object doString(String str,
275271
@Cached("createBinaryProfile()") ConditionProfile noWrapperProfile) {
276272
return PythonObjectNativeWrapper.wrap(factory().createString(str), noWrapperProfile);
277273
}
278274

279275
@Specialization
280-
Object doBoolean(boolean b) {
281-
return BoolNativeWrapper.create(b);
276+
Object doBoolean(boolean b,
277+
@Cached("createBinaryProfile()") ConditionProfile profile) {
278+
PInt boxed = factory().createInt(b);
279+
DynamicObjectNativeWrapper nativeWrapper = boxed.getNativeWrapper();
280+
if (profile.profile(nativeWrapper == null)) {
281+
nativeWrapper = BoolNativeWrapper.create(b);
282+
boxed.setNativeWrapper(nativeWrapper);
283+
}
284+
return nativeWrapper;
282285
}
283286

284287
@Specialization
@@ -368,7 +371,7 @@ public abstract static class AsPythonObjectNode extends CExtBaseNode {
368371

369372
@Child GetClassNode getClassNode;
370373

371-
@Specialization(guards = "!isMaterialized(object)")
374+
@Specialization
372375
boolean doBoolNativeWrapper(BoolNativeWrapper object) {
373376
return object.getValue();
374377
}
@@ -455,7 +458,7 @@ Object run(Object obj) {
455458
}
456459

457460
protected static boolean isPrimitiveNativeWrapper(PythonNativeWrapper object) {
458-
return object instanceof PrimitiveNativeWrapper && !isMaterialized((PrimitiveNativeWrapper) object);
461+
return object instanceof PrimitiveNativeWrapper && !isMaterialized((PrimitiveNativeWrapper) object) || object instanceof BoolNativeWrapper;
459462
}
460463

461464
protected boolean isForeignObject(TruffleObject obj) {
@@ -1150,7 +1153,7 @@ long runGeneric(Object value) {
11501153
private CastToIndexNode getIntNode() {
11511154
if (intNode == null) {
11521155
CompilerDirectives.transferToInterpreterAndInvalidate();
1153-
intNode = CastToIndexNode.createOverflow();
1156+
intNode = insert(CastToIndexNode.createOverflow());
11541157
}
11551158
return intNode;
11561159
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.graal.python.builtins.objects.cext;
42+
43+
import com.oracle.graal.python.builtins.objects.PythonAbstractObject;
44+
import com.oracle.truffle.api.interop.TruffleObject;
45+
46+
public class PythonNativeVoidPtr extends PythonAbstractObject {
47+
public final TruffleObject object;
48+
49+
public PythonNativeVoidPtr(TruffleObject object) {
50+
this.object = object;
51+
}
52+
53+
public int compareTo(Object o) {
54+
return 0;
55+
}
56+
57+
}

0 commit comments

Comments
 (0)