Skip to content

Commit 2fb6f17

Browse files
committed
Generalize creating native method wrappers
1 parent 2951f98 commit 2fb6f17

File tree

5 files changed

+35
-22
lines changed

5 files changed

+35
-22
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextSlotBuiltins.java

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@
175175
import static com.oracle.graal.python.nodes.SpecialMethodNames.T___SUB__;
176176
import static com.oracle.graal.python.nodes.SpecialMethodNames.T___TRUEDIV__;
177177
import static com.oracle.graal.python.nodes.SpecialMethodNames.T___XOR__;
178+
import static com.oracle.graal.python.util.PythonUtils.TS_ENCODING;
178179
import static com.oracle.graal.python.util.PythonUtils.tsLiteral;
179180

180181
import java.nio.charset.CharsetEncoder;
@@ -191,7 +192,7 @@
191192
import com.oracle.graal.python.builtins.objects.PythonAbstractObject.PInteropGetAttributeNode;
192193
import com.oracle.graal.python.builtins.objects.bytes.PByteArray;
193194
import com.oracle.graal.python.builtins.objects.bytes.PBytes;
194-
import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject;
195+
import com.oracle.graal.python.builtins.objects.cext.capi.CApiContext;
195196
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.AsCharPointerNode;
196197
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.LookupNativeMemberInMRONode;
197198
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.ObSizeNode;
@@ -230,7 +231,6 @@
230231
import com.oracle.graal.python.builtins.objects.dict.PDict;
231232
import com.oracle.graal.python.builtins.objects.frame.PFrame;
232233
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
233-
import com.oracle.graal.python.builtins.objects.function.PFunction;
234234
import com.oracle.graal.python.builtins.objects.function.PKeyword;
235235
import com.oracle.graal.python.builtins.objects.getsetdescriptor.GetSetDescriptor;
236236
import com.oracle.graal.python.builtins.objects.ints.PInt;
@@ -265,6 +265,7 @@
265265
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode;
266266
import com.oracle.graal.python.nodes.attributes.WriteAttributeToBuiltinTypeNode;
267267
import com.oracle.graal.python.nodes.attributes.WriteAttributeToObjectNode;
268+
import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
268269
import com.oracle.graal.python.nodes.object.BuiltinClassProfiles.InlineIsBuiltinClassProfile;
269270
import com.oracle.graal.python.nodes.object.BuiltinClassProfiles.IsBuiltinObjectProfile;
270271
import com.oracle.graal.python.nodes.object.GetDictIfExistsNode;
@@ -1979,9 +1980,11 @@ public Object get(@SuppressWarnings("unused") Object object) {
19791980
}
19801981

19811982
public abstract static class PyGetTypeSlotNode extends CApiUnaryBuiltinNode {
1983+
private final TruffleString name;
19821984
private @Child LookupAttributeInMRONode lookup;
19831985

19841986
PyGetTypeSlotNode(TruffleString name) {
1987+
this.name = name;
19851988
lookup = LookupAttributeInMRONode.create(name);
19861989
}
19871990

@@ -1996,28 +1999,26 @@ public Object getClass(PythonManagedClass object) {
19961999
}
19972000

19982001
@TruffleBoundary
1999-
private Object getProcsWrapper(Object object) {
2000-
Object value = lookup.execute(object);
2002+
private Object getProcsWrapper(Object type) {
2003+
Object value = lookup.execute(type);
20012004
if (value instanceof PNone) {
20022005
// both None and NO_VALUE can appear
20032006
return getNULL();
20042007
}
2005-
if (value instanceof PFunction) {
2006-
PFunction func = (PFunction) value;
2007-
if (func.procsWrapper != null) {
2008-
return func.procsWrapper;
2008+
/*
2009+
* The method can be a slot wrapper that already wraps a native slot function. If it
2010+
* matches in type and slot name, we should unwrap it to avoid nesting multiple
2011+
* wrappers.
2012+
*/
2013+
if (value instanceof PBuiltinFunction function) {
2014+
Object wrappedPtr = ExternalFunctionNodes.tryGetHiddenCallable(function);
2015+
if (wrappedPtr != null && name.equalsUncached(function.getName(), TS_ENCODING) &&
2016+
function.getEnclosingType() != null && IsSubtypeNode.getUncached().execute(type, function.getEnclosingType())) {
2017+
return wrappedPtr;
20092018
}
2010-
return func.procsWrapper = createProcsWrapper(value);
2011-
} else if (value instanceof PBuiltinFunction) {
2012-
PBuiltinFunction func = (PBuiltinFunction) value;
2013-
if (func.procsWrapper != null) {
2014-
return func.procsWrapper;
2015-
}
2016-
return func.procsWrapper = createProcsWrapper(value);
2017-
} else if (value instanceof PythonAbstractNativeObject) {
2018-
return ((PythonAbstractNativeObject) value).getPtr();
20192019
}
2020-
throw CompilerDirectives.shouldNotReachHere(value.getClass().getSimpleName());
2020+
CApiContext cApiContext = PythonContext.get(this).getCApiContext();
2021+
return cApiContext.getOrCreateProcWrapper(value, this::createProcsWrapper);
20212022
}
20222023

20232024
private Object createProcsWrapper(Object value) {

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
import java.util.Arrays;
5454
import java.util.HashMap;
5555
import java.util.HashSet;
56+
import java.util.IdentityHashMap;
5657
import java.util.Map;
5758
import java.util.Objects;
5859
import java.util.concurrent.ConcurrentHashMap;
@@ -100,6 +101,7 @@
100101
import com.oracle.graal.python.runtime.PythonContext.PythonThreadState;
101102
import com.oracle.graal.python.runtime.PythonOptions;
102103
import com.oracle.graal.python.runtime.exception.PException;
104+
import com.oracle.graal.python.util.Function;
103105
import com.oracle.graal.python.util.PythonUtils;
104106
import com.oracle.truffle.api.CallTarget;
105107
import com.oracle.truffle.api.CompilerAsserts;
@@ -195,6 +197,8 @@ public final class CApiContext extends CExtContext {
195197
private boolean loadNativeLibrary = true;
196198
public RootCallTarget signatureContainer;
197199

200+
private final IdentityHashMap<Object, Object> procWrappers = new IdentityHashMap<>();
201+
198202
public static TruffleLogger getLogger(Class<?> clazz) {
199203
return PythonLanguage.getLogger(LOGGER_CAPI_NAME + "." + clazz.getSimpleName());
200204
}
@@ -1050,4 +1054,9 @@ public void setClosurePointer(Object callable, Object closure, long pointer) {
10501054
public void retainClosure(Object closure) {
10511055
callableClosures.add(closure);
10521056
}
1057+
1058+
@TruffleBoundary
1059+
public Object getOrCreateProcWrapper(Object callable, Function<Object, Object> factory) {
1060+
return procWrappers.computeIfAbsent(callable, factory);
1061+
}
10531062
}

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,13 @@ public static PKeyword[] createKwDefaults(Object callable, Object closure) {
168168
return new PKeyword[]{new PKeyword(KW_CALLABLE, callable), new PKeyword(KW_CLOSURE, closure)};
169169
}
170170

171+
public static Object tryGetHiddenCallable(PBuiltinFunction function) {
172+
if (function.getFunctionRootNode() instanceof MethodDescriptorRoot) {
173+
return getHiddenCallable(function.getKwDefaults());
174+
}
175+
return null;
176+
}
177+
171178
public static Object getHiddenCallable(PKeyword[] kwDefaults) {
172179
if (kwDefaults.length >= KEYWORDS_HIDDEN_CALLABLE.length) {
173180
PKeyword kwDefault = kwDefaults[0];

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PBuiltinFunction.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,6 @@ public final class PBuiltinFunction extends PythonBuiltinObject implements Bound
7979
@CompilationFinal(dimensions = 1) private final Object[] defaults;
8080
@CompilationFinal(dimensions = 1) private final PKeyword[] kwDefaults;
8181

82-
public Object procsWrapper;
83-
8482
public PBuiltinFunction(PythonBuiltinClassType cls, Shape shape, TruffleString name, Object enclosingType, Object[] defaults, PKeyword[] kwDefaults, int flags, RootCallTarget callTarget) {
8583
super(cls, shape);
8684
this.name = PythonUtils.toPString(name);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/PFunction.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,6 @@ public final class PFunction extends PythonObject {
6363
@CompilationFinal(dimensions = 1) private Object[] defaultValues;
6464
@CompilationFinal(dimensions = 1) private PKeyword[] kwDefaultValues;
6565

66-
public Object procsWrapper;
67-
6866
public PFunction(PythonLanguage lang, TruffleString name, TruffleString qualname, PCode code, PythonObject globals, PCell[] closure) {
6967
this(lang, name, qualname, code, globals, PythonUtils.EMPTY_OBJECT_ARRAY, PKeyword.EMPTY_KEYWORDS, closure);
7068
}

0 commit comments

Comments
 (0)