Skip to content

Commit 4111ea4

Browse files
committed
[GR-34468] Various C API fixes.
PullRequest: graalpython/1998
2 parents f27db84 + 4ac0dd7 commit 4111ea4

File tree

7 files changed

+206
-11
lines changed

7 files changed

+206
-11
lines changed

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

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def compile_module(self, name):
9898
code='''int isNaN(double d) {
9999
return d != d;
100100
}
101-
101+
102102
int wrap_PyComplex_AsCComplex(PyObject* obj, double expectedReal, double expectedImag) {
103103
Py_complex res = PyComplex_AsCComplex(obj);
104104
if ((res.real == expectedReal && res.imag == expectedImag) || (isNaN(res.real) && isNaN(expectedReal))) {
@@ -120,6 +120,26 @@ def compile_module(self, name):
120120
callfunction="wrap_PyComplex_AsCComplex",
121121
)
122122

123+
test_PyComplex_cval = CPyExtFunction(
124+
lambda args: (args[0].real, args[0].imag) if type(args[0]) is complex else None,
125+
lambda: (
126+
(complex(1.0, 2.0), ),
127+
(DummyComplexSubclass(2.0, 3.0), ),
128+
),
129+
code='''
130+
PyObject* wrap_PyComplex_cval(PyObject* obj) {
131+
if (PyComplex_CheckExact(obj)) {
132+
Py_complex res = ((PyComplexObject *)obj)->cval;
133+
return PyTuple_Pack(2, PyFloat_FromDouble(res.real), PyFloat_FromDouble(res.imag));
134+
}
135+
return Py_None;
136+
}''',
137+
resultspec="O",
138+
argspec='O',
139+
arguments=["PyObject* obj"],
140+
callfunction="wrap_PyComplex_cval",
141+
)
142+
123143
test_PyComplex_RealAsDouble = CPyExtFunction(
124144
_reference_realasdouble,
125145
lambda: (
@@ -147,4 +167,3 @@ def compile_module(self, name):
147167
arguments=["PyObject* obj"],
148168
cmpfunc=unhandled_error_compare
149169
)
150-

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,8 @@ def compile_module(self, name):
694694
lambda: (
695695
(0, 0),
696696
(1, 1),
697+
(False, 0),
698+
(True, 1),
697699
(-1, -1),
698700
(1, 1),
699701
(1<<29, 1),

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,3 +182,23 @@ def compile_module(self, name):
182182
arguments=["PyObject* o", "PyObject* item"],
183183
cmpfunc=unhandled_error_compare
184184
)
185+
186+
test_PySet_GET_SIZE = CPyExtFunction(
187+
lambda args: len(args[0]),
188+
lambda: (
189+
(set(),),
190+
(set(),),
191+
(set([1, 2, 3]),),
192+
(set({'a', 'b'}),),
193+
(frozenset([1, 2, 3]),),
194+
(frozenset({'a', 'b'}),),
195+
(frozenset([None]),),
196+
(FrozenSetSubclass(),),
197+
(SetSubclass([None]),),
198+
),
199+
resultspec="n",
200+
argspec='O',
201+
arguments=["PyObject* o"],
202+
cmpfunc=unhandled_error_compare
203+
)
204+

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@
184184
import com.oracle.truffle.api.dsl.Cached;
185185
import com.oracle.truffle.api.dsl.Cached.Exclusive;
186186
import com.oracle.truffle.api.dsl.Cached.Shared;
187+
import com.oracle.truffle.api.dsl.Fallback;
187188
import com.oracle.truffle.api.dsl.GenerateUncached;
188189
import com.oracle.truffle.api.dsl.ImportStatic;
189190
import com.oracle.truffle.api.dsl.Specialization;
@@ -3182,12 +3183,17 @@ abstract static class ObSizeNode extends PNodeWithContext {
31823183
public abstract long execute(Object object);
31833184

31843185
@Specialization
3185-
long doInteger(@SuppressWarnings("unused") int object) {
3186+
static long doBoolean(boolean object) {
3187+
return object ? 1 : 0;
3188+
}
3189+
3190+
@Specialization
3191+
long doInteger(int object) {
31863192
return doLong(object);
31873193
}
31883194

31893195
@Specialization
3190-
long doLong(@SuppressWarnings("unused") long object) {
3196+
long doLong(long object) {
31913197
long t = PInt.abs(object);
31923198
int sign = object < 0 ? -1 : 1;
31933199
int size = 0;
@@ -3208,7 +3214,7 @@ long doPythonNativeVoidPtr(@SuppressWarnings("unused") PythonNativeVoidPtr objec
32083214
return ((Long.SIZE - 1) / getContext().getCApiContext().getPyLongBitsInDigit() + 1);
32093215
}
32103216

3211-
@Specialization(guards = "isFallback(object)")
3217+
@Fallback
32123218
static long doOther(Object object,
32133219
@Cached PyObjectSizeNode sizeNode) {
32143220
try {
@@ -3217,10 +3223,6 @@ static long doOther(Object object,
32173223
return -1;
32183224
}
32193225
}
3220-
3221-
static boolean isFallback(Object object) {
3222-
return !(object instanceof PInt || object instanceof Integer || object instanceof Long || object instanceof PythonNativeVoidPtr);
3223-
}
32243226
}
32253227

32263228
@GenerateUncached

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@
113113
import com.oracle.graal.python.builtins.objects.common.HashingStorage;
114114
import com.oracle.graal.python.builtins.objects.common.HashingStorageLibrary;
115115
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
116+
import com.oracle.graal.python.builtins.objects.complex.PComplex;
116117
import com.oracle.graal.python.builtins.objects.dict.PDict;
117118
import com.oracle.graal.python.builtins.objects.floats.PFloat;
118119
import com.oracle.graal.python.builtins.objects.frame.PFrame;
@@ -129,7 +130,7 @@
129130
import com.oracle.graal.python.builtins.objects.module.PythonModule;
130131
import com.oracle.graal.python.builtins.objects.object.PythonObject;
131132
import com.oracle.graal.python.builtins.objects.property.PProperty;
132-
import com.oracle.graal.python.builtins.objects.set.PSet;
133+
import com.oracle.graal.python.builtins.objects.set.PBaseSet;
133134
import com.oracle.graal.python.builtins.objects.slice.PSlice;
134135
import com.oracle.graal.python.builtins.objects.str.PString;
135136
import com.oracle.graal.python.builtins.objects.str.StringNodes.StringLenNode;
@@ -866,6 +867,11 @@ static Object doObDigit(PInt object, @SuppressWarnings("unused") PythonNativeWra
866867
return new PyLongDigitsWrapper(object);
867868
}
868869

870+
@Specialization(guards = "eq(COMPLEX_CVAL, key)")
871+
static Object doComplexCVal(PComplex object, @SuppressWarnings("unused") PythonNativeWrapper nativeWrapper, @SuppressWarnings("unused") String key) {
872+
return new PyComplexWrapper(object);
873+
}
874+
869875
@Specialization(guards = "eq(UNICODE_WSTR, key)")
870876
static Object doWstr(PString object, @SuppressWarnings("unused") PythonNativeWrapper nativeWrapper, @SuppressWarnings("unused") String key,
871877
@Shared("asWideCharNode") @Cached UnicodeAsWideCharNode asWideCharNode,
@@ -1059,7 +1065,7 @@ static Object doDQualname(PythonObject object, @SuppressWarnings("unused") Pytho
10591065
}
10601066

10611067
@Specialization(guards = "eq(SET_USED, key)", limit = "1")
1062-
static long doSetUsed(PSet object, @SuppressWarnings("unused") PythonNativeWrapper nativeWrapper, @SuppressWarnings("unused") String key,
1068+
static long doSetUsed(PBaseSet object, @SuppressWarnings("unused") PythonNativeWrapper nativeWrapper, @SuppressWarnings("unused") String key,
10631069
@CachedLibrary("object.getDictStorage()") HashingStorageLibrary lib) {
10641070
return lib.length(object.getDictStorage());
10651071
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,9 @@ public enum NativeMember {
191191
// PyLongObject
192192
OB_DIGIT("ob_digit"),
193193

194+
// PyComplexObject
195+
COMPLEX_CVAL("cval"),
196+
194197
// PySliceObject
195198
START("start", OBJECT),
196199
STOP("stop", OBJECT),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/*
2+
* Copyright (c) 2021, 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.capi;
42+
43+
import com.oracle.graal.python.builtins.objects.PythonAbstractObject;
44+
import com.oracle.graal.python.builtins.objects.cext.capi.CApiContext.LLVMType;
45+
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.GetLLVMType;
46+
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.IsPointerNode;
47+
import com.oracle.graal.python.builtins.objects.cext.capi.DynamicObjectNativeWrapper.ToNativeNode;
48+
import com.oracle.graal.python.builtins.objects.complex.PComplex;
49+
import com.oracle.truffle.api.CompilerDirectives;
50+
import com.oracle.truffle.api.dsl.Cached;
51+
import com.oracle.truffle.api.interop.InteropLibrary;
52+
import com.oracle.truffle.api.interop.UnknownIdentifierException;
53+
import com.oracle.truffle.api.interop.UnsupportedMessageException;
54+
import com.oracle.truffle.api.library.CachedLibrary;
55+
import com.oracle.truffle.api.library.ExportLibrary;
56+
import com.oracle.truffle.api.library.ExportMessage;
57+
import com.oracle.truffle.llvm.spi.NativeTypeLibrary;
58+
59+
/**
60+
* Emulates type {@code Py_complex}.
61+
*/
62+
@ExportLibrary(InteropLibrary.class)
63+
@ExportLibrary(value = NativeTypeLibrary.class, useForAOT = false)
64+
public final class PyComplexWrapper extends PythonNativeWrapper {
65+
66+
public static final String REAL = "real";
67+
public static final String IMAG = "imag";
68+
69+
public PyComplexWrapper(PComplex delegate) {
70+
super(delegate);
71+
}
72+
73+
public PComplex getPComplex(PythonNativeWrapperLibrary lib) {
74+
return (PComplex) lib.getDelegate(this);
75+
}
76+
77+
@ExportMessage
78+
@SuppressWarnings("static-method")
79+
boolean hasMembers() {
80+
return true;
81+
}
82+
83+
@ExportMessage
84+
@SuppressWarnings("static-method")
85+
Object getMembers(@SuppressWarnings("unused") boolean includeInternal) {
86+
return new PythonAbstractObject.Keys(new Object[]{REAL, IMAG});
87+
}
88+
89+
@ExportMessage
90+
@SuppressWarnings("static-method")
91+
boolean isMemberReadable(String key) {
92+
return REAL.equals(key) || IMAG.equals(key);
93+
}
94+
95+
@ExportMessage
96+
Object readMember(String key,
97+
@CachedLibrary("this") PythonNativeWrapperLibrary lib) throws UnknownIdentifierException {
98+
switch (key) {
99+
case REAL:
100+
return getPComplex(lib).getReal();
101+
case IMAG:
102+
return getPComplex(lib).getImag();
103+
}
104+
CompilerDirectives.transferToInterpreterAndInvalidate();
105+
throw UnknownIdentifierException.create(key);
106+
}
107+
108+
@ExportMessage
109+
void toNative(
110+
@Cached ToNativeNode toNativeNode) {
111+
toNativeNode.execute(this);
112+
}
113+
114+
@ExportMessage
115+
boolean isPointer(
116+
@Cached IsPointerNode pIsPointerNode) {
117+
return pIsPointerNode.execute(this);
118+
}
119+
120+
@ExportMessage
121+
long asPointer(
122+
@CachedLibrary(limit = "1") InteropLibrary interopLib,
123+
@CachedLibrary("this") PythonNativeWrapperLibrary lib) throws UnsupportedMessageException {
124+
Object nativePointer = lib.getNativePointer(this);
125+
if (nativePointer instanceof Long) {
126+
return (long) nativePointer;
127+
}
128+
return interopLib.asPointer(nativePointer);
129+
}
130+
131+
@ExportMessage
132+
@SuppressWarnings("static-method")
133+
boolean hasNativeType() {
134+
return true;
135+
}
136+
137+
@ExportMessage
138+
@SuppressWarnings("static-method")
139+
Object getNativeType(
140+
@Cached GetLLVMType getLLVMType) {
141+
return getLLVMType.execute(LLVMType.Py_complex);
142+
}
143+
}

0 commit comments

Comments
 (0)