Skip to content

Commit 7d79596

Browse files
committed
Correctly wrap type name to get 'char*' on TO_NATIVE.
1 parent 25c001c commit 7d79596

File tree

8 files changed

+350
-27
lines changed

8 files changed

+350
-27
lines changed

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

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@
6060
import com.oracle.graal.python.builtins.objects.bytes.BytesBuiltins;
6161
import com.oracle.graal.python.builtins.objects.bytes.PBytes;
6262
import com.oracle.graal.python.builtins.objects.cext.CExtNodes;
63-
import com.oracle.graal.python.builtins.objects.cext.NativeCAPISymbols;
6463
import com.oracle.graal.python.builtins.objects.cext.PythonObjectNativeWrapper;
6564
import com.oracle.graal.python.builtins.objects.cext.UnicodeObjectNodes.UnicodeAsWideCharNode;
6665
import com.oracle.graal.python.builtins.objects.complex.PComplex;
@@ -150,24 +149,7 @@ boolean run(Object value) {
150149
@Builtin(name = "to_char_pointer", fixedNumOfArguments = 1)
151150
@GenerateNodeFactory
152151
abstract static class TruffleString_AsString extends NativeBuiltin {
153-
@CompilationFinal TruffleObject truffle_string_to_cstr;
154-
@Child private Node executeNode;
155-
156-
TruffleObject getTruffleStringToCstr() {
157-
if (truffle_string_to_cstr == null) {
158-
CompilerDirectives.transferToInterpreterAndInvalidate();
159-
truffle_string_to_cstr = (TruffleObject) getContext().getEnv().importSymbol(NativeCAPISymbols.FUN_PY_TRUFFLE_STRING_TO_CSTR);
160-
}
161-
return truffle_string_to_cstr;
162-
}
163-
164-
private Node getExecuteNode() {
165-
if (executeNode == null) {
166-
CompilerDirectives.transferToInterpreterAndInvalidate();
167-
executeNode = insert(Message.createExecute(1).createNode());
168-
}
169-
return executeNode;
170-
}
152+
@Child private CExtNodes.AsCharPointer asCharPointerNode;
171153

172154
@Specialization
173155
Object run(PString str) {
@@ -176,11 +158,11 @@ Object run(PString str) {
176158

177159
@Specialization
178160
Object run(String str) {
179-
try {
180-
return ForeignAccess.sendExecute(getExecuteNode(), getTruffleStringToCstr(), str);
181-
} catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) {
182-
throw e.raise();
161+
if (asCharPointerNode == null) {
162+
CompilerDirectives.transferToInterpreterAndInvalidate();
163+
asCharPointerNode = insert(CExtNodes.AsCharPointer.create());
183164
}
165+
return asCharPointerNode.execute(str);
184166
}
185167

186168
@Fallback

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

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@
4141
import com.oracle.graal.python.PythonLanguage;
4242
import com.oracle.graal.python.builtins.objects.PNone;
4343
import com.oracle.graal.python.builtins.objects.PythonAbstractObject;
44+
import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.AsCharPointerNodeGen;
4445
import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.AsPythonObjectNodeGen;
4546
import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.ToSulongNodeGen;
47+
import com.oracle.graal.python.builtins.objects.type.PythonClass;
4648
import com.oracle.graal.python.nodes.PBaseNode;
4749
import com.oracle.graal.python.nodes.PGuards;
4850
import com.oracle.graal.python.nodes.object.GetClassNode;
@@ -52,7 +54,13 @@
5254
import com.oracle.truffle.api.dsl.Fallback;
5355
import com.oracle.truffle.api.dsl.ImportStatic;
5456
import com.oracle.truffle.api.dsl.Specialization;
57+
import com.oracle.truffle.api.interop.ArityException;
58+
import com.oracle.truffle.api.interop.ForeignAccess;
59+
import com.oracle.truffle.api.interop.Message;
5560
import com.oracle.truffle.api.interop.TruffleObject;
61+
import com.oracle.truffle.api.interop.UnsupportedMessageException;
62+
import com.oracle.truffle.api.interop.UnsupportedTypeException;
63+
import com.oracle.truffle.api.nodes.Node;
5664
import com.oracle.truffle.api.profiles.ConditionProfile;
5765

5866
public abstract class CExtNodes {
@@ -102,7 +110,12 @@ Object runNativeObject(PythonNativeObject object) {
102110
return object.object;
103111
}
104112

105-
@Specialization(guards = {"!isNativeClass(object)", "!isNativeObject(object)", "!isNoValue(object)"})
113+
@Specialization(guards = "!isNativeClass(object)")
114+
Object runNativeObject(PythonClass object) {
115+
return PythonClassNativeWrapper.wrap(object);
116+
}
117+
118+
@Specialization(guards = {"!isPythonClass(object)", "!isNativeObject(object)", "!isNoValue(object)"})
106119
Object runNativeObject(PythonAbstractObject object) {
107120
assert object != PNone.NO_VALUE;
108121
return PythonObjectNativeWrapper.wrap(object);
@@ -117,6 +130,10 @@ protected static boolean isNativeClass(PythonAbstractObject o) {
117130
return o instanceof PythonNativeClass;
118131
}
119132

133+
protected static boolean isPythonClass(PythonAbstractObject o) {
134+
return o instanceof PythonClass;
135+
}
136+
120137
protected static boolean isNativeObject(PythonAbstractObject o) {
121138
return o instanceof PythonNativeObject;
122139
}
@@ -196,4 +213,41 @@ public static ToJavaNode create() {
196213

197214
}
198215

216+
public abstract static class AsCharPointer extends PBaseNode {
217+
218+
@CompilationFinal TruffleObject truffle_string_to_cstr;
219+
@Child private Node executeNode;
220+
221+
public abstract Object execute(String s);
222+
223+
TruffleObject getTruffleStringToCstr() {
224+
if (truffle_string_to_cstr == null) {
225+
CompilerDirectives.transferToInterpreterAndInvalidate();
226+
truffle_string_to_cstr = (TruffleObject) getContext().getEnv().importSymbol(NativeCAPISymbols.FUN_PY_TRUFFLE_STRING_TO_CSTR);
227+
}
228+
return truffle_string_to_cstr;
229+
}
230+
231+
private Node getExecuteNode() {
232+
if (executeNode == null) {
233+
CompilerDirectives.transferToInterpreterAndInvalidate();
234+
executeNode = insert(Message.createExecute(1).createNode());
235+
}
236+
return executeNode;
237+
}
238+
239+
@Specialization
240+
Object doString(String str) {
241+
try {
242+
return ForeignAccess.sendExecute(getExecuteNode(), getTruffleStringToCstr(), str);
243+
} catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) {
244+
throw e.raise();
245+
}
246+
}
247+
248+
public static AsCharPointer create() {
249+
return AsCharPointerNodeGen.create();
250+
}
251+
}
252+
199253
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright (c) 2018, Oracle and/or its affiliates.
3+
*
4+
* The Universal Permissive License (UPL), Version 1.0
5+
*
6+
* Subject to the condition set forth below, permission is hereby granted to any
7+
* person obtaining a copy of this software, associated documentation and/or data
8+
* (collectively the "Software"), free of charge and under any and all copyright
9+
* rights in the Software, and any and all patent rights owned or freely
10+
* licensable by each licensor hereunder covering either (i) the unmodified
11+
* Software as contributed to or provided by such licensor, or (ii) the Larger
12+
* Works (as defined below), to deal in both
13+
*
14+
* (a) the Software, and
15+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
16+
* one is included with the Software (each a "Larger Work" to which the
17+
* Software is contributed by such licensors),
18+
*
19+
* without restriction, including without limitation the rights to copy, create
20+
* derivative works of, display, perform, and distribute the Software and make,
21+
* use, sell, offer for sale, import, export, have made, and have sold the
22+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
23+
* either these or other terms.
24+
*
25+
* This license is subject to the following condition:
26+
*
27+
* The above copyright notice and either this complete permission notice or at a
28+
* minimum a reference to the UPL must be included in all copies or substantial
29+
* portions of the Software.
30+
*
31+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37+
* SOFTWARE.
38+
*/
39+
package com.oracle.graal.python.builtins.objects.cext;
40+
41+
import com.oracle.graal.python.PythonLanguage;
42+
import com.oracle.truffle.api.interop.ForeignAccess;
43+
import com.oracle.truffle.api.interop.Message;
44+
import com.oracle.truffle.api.interop.TruffleObject;
45+
46+
/**
47+
* Unlike a {@link PythonObjectNativeWrapper} object that wraps a Python unicode object, this
48+
* wrapper let's a Java String look like a {@code char*}.
49+
*/
50+
public class CStringWrapper implements TruffleObject {
51+
52+
private final String delegate;
53+
private Object nativePointer;
54+
55+
public CStringWrapper(String delegate) {
56+
this.delegate = delegate;
57+
}
58+
59+
public String getDelegate() {
60+
return delegate;
61+
}
62+
63+
public Object getNativePointer() {
64+
return nativePointer;
65+
}
66+
67+
public void setNativePointer(Object nativePointer) {
68+
assert this.nativePointer == null;
69+
this.nativePointer = nativePointer;
70+
}
71+
72+
public boolean isNative() {
73+
return nativePointer != null;
74+
}
75+
76+
@Override
77+
protected void finalize() throws Throwable {
78+
if (nativePointer != null) {
79+
TruffleObject freeCString = (TruffleObject) PythonLanguage.getContext().getEnv().importSymbol("truffle_free_cstr");
80+
assert freeCString != null;
81+
try {
82+
ForeignAccess.sendExecute(Message.createExecute(1).createNode(), freeCString, nativePointer);
83+
} catch (Exception e) {
84+
// ignore
85+
}
86+
}
87+
}
88+
89+
static boolean isInstance(TruffleObject o) {
90+
return o instanceof CStringWrapper;
91+
}
92+
93+
public ForeignAccess getForeignAccess() {
94+
return CStringWrapperMRForeign.ACCESS;
95+
}
96+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* Copyright (c) 2018, Oracle and/or its affiliates.
3+
*
4+
* The Universal Permissive License (UPL), Version 1.0
5+
*
6+
* Subject to the condition set forth below, permission is hereby granted to any
7+
* person obtaining a copy of this software, associated documentation and/or data
8+
* (collectively the "Software"), free of charge and under any and all copyright
9+
* rights in the Software, and any and all patent rights owned or freely
10+
* licensable by each licensor hereunder covering either (i) the unmodified
11+
* Software as contributed to or provided by such licensor, or (ii) the Larger
12+
* Works (as defined below), to deal in both
13+
*
14+
* (a) the Software, and
15+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
16+
* one is included with the Software (each a "Larger Work" to which the
17+
* Software is contributed by such licensors),
18+
*
19+
* without restriction, including without limitation the rights to copy, create
20+
* derivative works of, display, perform, and distribute the Software and make,
21+
* use, sell, offer for sale, import, export, have made, and have sold the
22+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
23+
* either these or other terms.
24+
*
25+
* This license is subject to the following condition:
26+
*
27+
* The above copyright notice and either this complete permission notice or at a
28+
* minimum a reference to the UPL must be included in all copies or substantial
29+
* portions of the Software.
30+
*
31+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37+
* SOFTWARE.
38+
*/
39+
package com.oracle.graal.python.builtins.objects.cext;
40+
41+
import com.oracle.truffle.api.CompilerDirectives;
42+
import com.oracle.truffle.api.interop.ForeignAccess;
43+
import com.oracle.truffle.api.interop.Message;
44+
import com.oracle.truffle.api.interop.MessageResolution;
45+
import com.oracle.truffle.api.interop.Resolve;
46+
import com.oracle.truffle.api.interop.TruffleObject;
47+
import com.oracle.truffle.api.interop.UnknownIdentifierException;
48+
import com.oracle.truffle.api.interop.UnsupportedMessageException;
49+
import com.oracle.truffle.api.nodes.Node;
50+
51+
@MessageResolution(receiverType = PyNumberMethodsWrapper.class)
52+
public class CStringWrapperMR {
53+
54+
@Resolve(message = "READ")
55+
abstract static class ReadNode extends Node {
56+
57+
public Object access(CStringWrapper object, int idx) {
58+
String s = object.getDelegate();
59+
if (idx >= 0 && idx < s.length()) {
60+
return s.charAt(idx);
61+
} else if (idx == s.length()) {
62+
return 0;
63+
}
64+
throw UnknownIdentifierException.raise(Integer.toString(idx));
65+
}
66+
}
67+
68+
@Resolve(message = "IS_POINTER")
69+
abstract static class IsPointerNode extends Node {
70+
boolean access(CStringWrapper obj) {
71+
return obj.isNative();
72+
}
73+
}
74+
75+
@Resolve(message = "AS_POINTER")
76+
abstract static class AsPointerNode extends Node {
77+
@Child private Node asPointerNode;
78+
79+
long access(CStringWrapper obj) {
80+
// the native pointer object must either be a TruffleObject or a primitive
81+
Object nativePointer = obj.getNativePointer();
82+
if (nativePointer instanceof TruffleObject) {
83+
if (asPointerNode == null) {
84+
CompilerDirectives.transferToInterpreterAndInvalidate();
85+
asPointerNode = insert(Message.AS_POINTER.createNode());
86+
}
87+
try {
88+
return ForeignAccess.sendAsPointer(asPointerNode, (TruffleObject) nativePointer);
89+
} catch (UnsupportedMessageException e) {
90+
throw e.raise();
91+
}
92+
}
93+
return (long) nativePointer;
94+
95+
}
96+
}
97+
98+
@Resolve(message = "TO_NATIVE")
99+
abstract static class ToNativeNode extends Node {
100+
@Child private CExtNodes.AsCharPointer asCharPointerNode;
101+
102+
Object access(CStringWrapper obj) {
103+
if (!obj.isNative()) {
104+
if (asCharPointerNode == null) {
105+
CompilerDirectives.transferToInterpreterAndInvalidate();
106+
asCharPointerNode = insert(CExtNodes.AsCharPointer.create());
107+
}
108+
Object ptr = asCharPointerNode.execute(obj.getDelegate());
109+
obj.setNativePointer(ptr);
110+
}
111+
return obj;
112+
}
113+
}
114+
115+
}

0 commit comments

Comments
 (0)