Skip to content

Commit 406a7c3

Browse files
committed
Refactor native wrappers and also wrap foreign objects.
1 parent d569b7a commit 406a7c3

13 files changed

+267
-338
lines changed

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

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,9 @@
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.PythonClassNativeWrapper;
64-
import com.oracle.graal.python.builtins.objects.cext.PythonObjectNativeWrapper;
63+
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonClassNativeWrapper;
64+
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonNativeWrapper;
65+
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonObjectNativeWrapper;
6566
import com.oracle.graal.python.builtins.objects.cext.UnicodeObjectNodes.UnicodeAsWideCharNode;
6667
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes;
6768
import com.oracle.graal.python.builtins.objects.complex.PComplex;
@@ -231,9 +232,9 @@ long run(PFloat value) {
231232
}
232233

233234
@Specialization
234-
Object run(PythonObjectNativeWrapper value,
235+
Object run(PythonNativeWrapper value,
235236
@Cached("create()") AsLong recursive) {
236-
return recursive.executeWith(value.getPythonObject());
237+
return recursive.executeWith(value.getDelegate());
237238
}
238239

239240
private BuiltinConstructors.IntNode getIntNode() {
@@ -634,8 +635,8 @@ private Object checkFunctionResult(Object result) {
634635
abstract static class PNativeToPTypeNode extends PForeignToPTypeNode {
635636

636637
@Specialization
637-
protected static PythonAbstractObject fromNativeNone(PythonObjectNativeWrapper nativeWrapper) {
638-
return nativeWrapper.getPythonObject();
638+
protected static Object fromNativeNone(PythonNativeWrapper nativeWrapper) {
639+
return nativeWrapper.getDelegate();
639640
}
640641

641642
public static PNativeToPTypeNode create() {
@@ -1040,8 +1041,8 @@ abstract static class PyTruffle_GetTpFlags extends NativeBuiltin {
10401041
@Child private GetClassNode getClassNode;
10411042

10421043
@Specialization
1043-
long doPythonObject(PythonObjectNativeWrapper nativeWrapper) {
1044-
PythonClass pclass = getClassNode().execute(nativeWrapper.getPythonObject());
1044+
long doPythonObject(PythonNativeWrapper nativeWrapper) {
1045+
PythonClass pclass = getClassNode().execute(nativeWrapper.getDelegate());
10451046
return pclass.getFlags();
10461047
}
10471048

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/PythonAbstractObject.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
*/
3939
package com.oracle.graal.python.builtins.objects;
4040

41-
import com.oracle.graal.python.builtins.objects.cext.PythonObjectNativeWrapper;
41+
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonObjectNativeWrapper;
4242
import com.oracle.graal.python.runtime.interop.PythonMessageResolutionForeign;
4343
import com.oracle.truffle.api.interop.ForeignAccess;
4444
import com.oracle.truffle.api.interop.TruffleObject;

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

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@
4545
import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.AsPythonObjectNodeGen;
4646
import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.ToJavaNodeGen;
4747
import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.ToSulongNodeGen;
48+
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonClassNativeWrapper;
49+
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonNativeWrapper;
50+
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonObjectNativeWrapper;
51+
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.TruffleObjectNativeWrapper;
4852
import com.oracle.graal.python.builtins.objects.type.PythonClass;
4953
import com.oracle.graal.python.nodes.PBaseNode;
5054
import com.oracle.graal.python.nodes.PGuards;
@@ -77,42 +81,42 @@ public abstract static class ToSulongNode extends PBaseNode {
7781
* passed from Python into C code need to wrap Strings into PStrings.
7882
*/
7983
@Specialization
80-
Object run(String str) {
84+
Object doString(String str) {
8185
return PythonObjectNativeWrapper.wrap(factory().createString(str));
8286
}
8387

8488
@Specialization
85-
Object run(boolean b) {
89+
Object doBoolean(boolean b) {
8690
return PythonObjectNativeWrapper.wrap(factory().createInt(b));
8791
}
8892

8993
@Specialization
90-
Object run(int integer) {
91-
return PythonObjectNativeWrapper.wrap(factory().createInt(integer));
94+
Object doInteger(int i) {
95+
return PythonObjectNativeWrapper.wrap(factory().createInt(i));
9296
}
9397

9498
@Specialization
95-
Object run(long integer) {
96-
return PythonObjectNativeWrapper.wrap(factory().createInt(integer));
99+
Object doLong(long l) {
100+
return PythonObjectNativeWrapper.wrap(factory().createInt(l));
97101
}
98102

99103
@Specialization
100-
Object run(double number) {
101-
return PythonObjectNativeWrapper.wrap(factory().createFloat(number));
104+
Object doDouble(double d) {
105+
return PythonObjectNativeWrapper.wrap(factory().createFloat(d));
102106
}
103107

104108
@Specialization
105-
Object runNativeClass(PythonNativeClass object) {
106-
return object.object;
109+
Object doNativeClass(PythonNativeClass nativeClass) {
110+
return nativeClass.object;
107111
}
108112

109113
@Specialization
110-
Object runNativeObject(PythonNativeObject object) {
111-
return object.object;
114+
Object doNativeObject(PythonNativeObject nativeObject) {
115+
return nativeObject.object;
112116
}
113117

114118
@Specialization(guards = "!isNativeClass(object)")
115-
Object runNativeObject(PythonClass object) {
119+
Object doPythonClass(PythonClass object) {
116120
return PythonClassNativeWrapper.wrap(object);
117121
}
118122

@@ -122,6 +126,11 @@ Object runNativeObject(PythonAbstractObject object) {
122126
return PythonObjectNativeWrapper.wrap(object);
123127
}
124128

129+
@Specialization(guards = {"isForeignObject(object)"})
130+
Object doPythonClass(TruffleObject object) {
131+
return TruffleObjectNativeWrapper.wrap(object);
132+
}
133+
125134
@Fallback
126135
Object run(Object obj) {
127136
assert obj != null : "Java 'null' cannot be a Sulong value";
@@ -140,6 +149,10 @@ protected static boolean isNativeObject(PythonAbstractObject o) {
140149
return o instanceof PythonNativeObject;
141150
}
142151

152+
protected static boolean isForeignObject(Object o) {
153+
return !(o instanceof PythonAbstractObject);
154+
}
155+
143156
public static ToSulongNode create() {
144157
return ToSulongNodeGen.create();
145158
}
@@ -156,8 +169,8 @@ public abstract static class AsPythonObjectNode extends PBaseNode {
156169
@Child GetClassNode getClassNode;
157170

158171
@Specialization
159-
PythonAbstractObject doNativeWrapper(PythonObjectNativeWrapper object) {
160-
return object.getPythonObject();
172+
Object doNativeWrapper(PythonNativeWrapper object) {
173+
return object.getDelegate();
161174
}
162175

163176
@Specialization(guards = {"isForeignObject(object)", "!isNativeWrapper(object)"})
@@ -210,8 +223,8 @@ protected boolean isNativeWrapper(Object obj) {
210223

211224
@TruffleBoundary
212225
public static Object doSlowPath(Object object) {
213-
if (object instanceof PythonObjectNativeWrapper) {
214-
return ((PythonObjectNativeWrapper) object).getPythonObject();
226+
if (object instanceof PythonNativeWrapper) {
227+
return ((PythonNativeWrapper) object).getDelegate();
215228
} else if (GetClassNode.getItSlowPath(object) == PythonLanguage.getCore().getForeignClass()) {
216229
throw new AssertionError("Unsupported slow path operation: converting 'to_java(" + object + ")");
217230
}

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,10 @@
4242
import com.oracle.truffle.api.interop.TruffleObject;
4343

4444
/**
45-
* Unlike a {@link PythonObjectNativeWrapper} object that wraps a Python unicode object, this
46-
* wrapper let's a Java String look like a {@code char*}.
45+
* Unlike a
46+
* {@link com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonObjectNativeWrapper}
47+
* object that wraps a Python unicode object, this wrapper let's a Java String look like a
48+
* {@code char*}.
4749
*/
4850
public class CStringWrapper implements TruffleObject {
4951

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
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.builtins.objects.PythonAbstractObject;
42+
import com.oracle.graal.python.builtins.objects.type.PythonClass;
43+
import com.oracle.truffle.api.interop.ForeignAccess;
44+
import com.oracle.truffle.api.interop.TruffleObject;
45+
46+
public abstract class NativeWrappers {
47+
public abstract static class PythonNativeWrapper implements TruffleObject {
48+
49+
private Object nativePointer;
50+
51+
public abstract Object getDelegate();
52+
53+
public Object getNativePointer() {
54+
return nativePointer;
55+
}
56+
57+
public void setNativePointer(Object nativePointer) {
58+
// we should set the pointer just once
59+
assert this.nativePointer == null || this.nativePointer.equals(nativePointer);
60+
this.nativePointer = nativePointer;
61+
}
62+
63+
public boolean isNative() {
64+
return nativePointer != null;
65+
}
66+
67+
@Override
68+
public ForeignAccess getForeignAccess() {
69+
return PythonObjectNativeWrapperMRForeign.ACCESS;
70+
}
71+
}
72+
73+
/**
74+
* Used to wrap {@link PythonAbstractObject} when used in native code. This wrapper mimics the
75+
* correct shape of the corresponding native type {@code struct _object}.
76+
*/
77+
public static class PythonObjectNativeWrapper extends PythonNativeWrapper {
78+
private final PythonAbstractObject pythonObject;
79+
80+
public PythonObjectNativeWrapper(PythonAbstractObject object) {
81+
this.pythonObject = object;
82+
}
83+
84+
public PythonAbstractObject getPythonObject() {
85+
return pythonObject;
86+
}
87+
88+
public static boolean isInstance(TruffleObject o) {
89+
return o instanceof PythonObjectNativeWrapper;
90+
}
91+
92+
public static PythonObjectNativeWrapper wrap(PythonAbstractObject obj) {
93+
// important: native wrappers are cached
94+
PythonObjectNativeWrapper nativeWrapper = obj.getNativeWrapper();
95+
if (nativeWrapper == null) {
96+
nativeWrapper = new PythonObjectNativeWrapper(obj);
97+
obj.setNativeWrapper(nativeWrapper);
98+
}
99+
return nativeWrapper;
100+
}
101+
102+
@Override
103+
public Object getDelegate() {
104+
return pythonObject;
105+
}
106+
}
107+
108+
/**
109+
* Used to wrap {@link PythonClass} when used in native code. This wrapper mimics the correct
110+
* shape of the corresponding native type {@code struct _typeobject}.
111+
*/
112+
public static class PythonClassNativeWrapper extends PythonObjectNativeWrapper {
113+
private final CStringWrapper nameWrapper;
114+
private Object getBufferProc;
115+
private Object releaseBufferProc;
116+
117+
public PythonClassNativeWrapper(PythonClass object) {
118+
super(object);
119+
this.nameWrapper = new CStringWrapper(object.getName());
120+
}
121+
122+
public CStringWrapper getNameWrapper() {
123+
return nameWrapper;
124+
}
125+
126+
public Object getGetBufferProc() {
127+
return getBufferProc;
128+
}
129+
130+
public void setGetBufferProc(Object getBufferProc) {
131+
this.getBufferProc = getBufferProc;
132+
}
133+
134+
public Object getReleaseBufferProc() {
135+
return releaseBufferProc;
136+
}
137+
138+
public void setReleaseBufferProc(Object releaseBufferProc) {
139+
this.releaseBufferProc = releaseBufferProc;
140+
}
141+
142+
public static PythonClassNativeWrapper wrap(PythonClass obj) {
143+
// important: native wrappers are cached
144+
PythonClassNativeWrapper nativeWrapper = obj.getNativeWrapper();
145+
if (nativeWrapper == null) {
146+
nativeWrapper = new PythonClassNativeWrapper(obj);
147+
obj.setNativeWrapper(nativeWrapper);
148+
}
149+
return nativeWrapper;
150+
}
151+
152+
}
153+
154+
/**
155+
* Wraps a sequence object (like a list) such that it behaves like a bare C array.
156+
*/
157+
public static class PySequenceArrayWrapper extends PythonNativeWrapper {
158+
159+
private final Object delegate;
160+
161+
public PySequenceArrayWrapper(Object delegate) {
162+
this.delegate = delegate;
163+
}
164+
165+
@Override
166+
public Object getDelegate() {
167+
return delegate;
168+
}
169+
170+
static boolean isInstance(TruffleObject o) {
171+
return o instanceof PySequenceArrayWrapper;
172+
}
173+
174+
@Override
175+
public ForeignAccess getForeignAccess() {
176+
return PySequenceArrayWrapperMRForeign.ACCESS;
177+
}
178+
}
179+
180+
public static class TruffleObjectNativeWrapper extends PythonNativeWrapper {
181+
private final TruffleObject foreignObject;
182+
183+
public TruffleObjectNativeWrapper(TruffleObject foreignObject) {
184+
this.foreignObject = foreignObject;
185+
}
186+
187+
public TruffleObject getForeignObject() {
188+
return foreignObject;
189+
}
190+
191+
public static TruffleObjectNativeWrapper wrap(TruffleObject foreignObject) {
192+
return new TruffleObjectNativeWrapper(foreignObject);
193+
}
194+
195+
@Override
196+
public Object getDelegate() {
197+
return foreignObject;
198+
}
199+
}
200+
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040

4141
import com.oracle.graal.python.builtins.objects.PNone;
4242
import com.oracle.graal.python.builtins.objects.cext.CExtNodes.ToSulongNode;
43+
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonClassNativeWrapper;
4344
import com.oracle.truffle.api.CompilerDirectives;
4445
import com.oracle.truffle.api.interop.MessageResolution;
4546
import com.oracle.truffle.api.interop.Resolve;
@@ -70,8 +71,9 @@ public Object access(PyBufferProcsWrapper object, String key) {
7071
// TODO extend list
7172
throw UnknownIdentifierException.raise(key);
7273
}
74+
// do not wrap result if exists since this is directly a native object
7375
// use NO_VALUE for NULL
74-
return getToSulongNode().execute(result == null ? PNone.NO_VALUE : result);
76+
return result == null ? getToSulongNode().execute(PNone.NO_VALUE) : result;
7577
}
7678

7779
private ToSulongNode getToSulongNode() {

0 commit comments

Comments
 (0)