|
73 | 73 | import static com.oracle.graal.python.util.PythonUtils.TS_ENCODING; |
74 | 74 | import static com.oracle.graal.python.util.PythonUtils.toTruffleStringUncached; |
75 | 75 | import static com.oracle.truffle.api.CompilerDirectives.shouldNotReachHere; |
76 | | -import static com.oracle.truffle.api.CompilerDirectives.transferToInterpreterAndInvalidate; |
77 | 76 |
|
78 | 77 | import java.util.regex.Matcher; |
79 | 78 | import java.util.regex.Pattern; |
|
91 | 90 | import com.oracle.graal.python.builtins.objects.cext.PythonNativeVoidPtr; |
92 | 91 | import com.oracle.graal.python.builtins.objects.cext.capi.CApiContext.ModuleSpec; |
93 | 92 | import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodesFactory.AsCharPointerNodeGen; |
94 | | -import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodesFactory.CreateFunctionNodeGen; |
95 | 93 | import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodesFactory.FromCharPointerNodeGen; |
96 | 94 | import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodesFactory.PyErrFetchNodeGen; |
97 | 95 | import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodesFactory.PyErrOccurredNodeGen; |
|
101 | 99 | import com.oracle.graal.python.builtins.objects.cext.capi.ExternalFunctionNodes.DefaultCheckFunctionResultNode; |
102 | 100 | import com.oracle.graal.python.builtins.objects.cext.capi.ExternalFunctionNodes.ExternalFunctionInvokeNode; |
103 | 101 | import com.oracle.graal.python.builtins.objects.cext.capi.ExternalFunctionNodes.PExternalFunctionWrapper; |
104 | | -import com.oracle.graal.python.builtins.objects.cext.capi.PyProcsWrapper.TpSlotWrapper; |
105 | 102 | import com.oracle.graal.python.builtins.objects.cext.capi.PythonNativeWrapper.PythonAbstractObjectNativeWrapper; |
106 | 103 | import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions; |
107 | 104 | import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions.HandlePointerConverter; |
|
151 | 148 | import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroStorageNode; |
152 | 149 | import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetTypeFlagsNode; |
153 | 150 | import com.oracle.graal.python.builtins.objects.type.TypeNodes.ProfileClassNode; |
154 | | -import com.oracle.graal.python.builtins.objects.type.slots.TpSlot.TpSlotBuiltin; |
155 | | -import com.oracle.graal.python.builtins.objects.type.slots.TpSlot.TpSlotNative; |
156 | | -import com.oracle.graal.python.builtins.objects.type.slots.TpSlot.TpSlotPython; |
157 | 151 | import com.oracle.graal.python.lib.PyFloatAsDoubleNode; |
158 | 152 | import com.oracle.graal.python.lib.PyNumberAsSizeNode; |
159 | 153 | import com.oracle.graal.python.lib.PyObjectLookupAttr; |
|
195 | 189 | import com.oracle.truffle.api.CompilerDirectives; |
196 | 190 | import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; |
197 | 191 | import com.oracle.truffle.api.RootCallTarget; |
198 | | -import com.oracle.truffle.api.TruffleLogger; |
199 | 192 | import com.oracle.truffle.api.dsl.Bind; |
200 | 193 | import com.oracle.truffle.api.dsl.Cached; |
201 | 194 | import com.oracle.truffle.api.dsl.Cached.Exclusive; |
@@ -888,7 +881,7 @@ public static PCallCapiFunction getUncached() { |
888 | 881 | * <p> |
889 | 882 | * This method basically implements the native member inheritance that is done by |
890 | 883 | * {@code inherit_special} or other code in {@code PyType_Ready}. In addition, we do a special |
891 | | - * case for special slots assignment that happens within {@Code type_new_alloc} for heap types. |
| 884 | + * case for special slots assignment that happens within {@code type_new_alloc} for heap types. |
892 | 885 | * </p> |
893 | 886 | * <p> |
894 | 887 | * Since it may be that a managed types needs to emulate such members but there is no |
@@ -1974,7 +1967,7 @@ static PBuiltinFunction doIt(Node inliningTarget, Object methodDef, int element, |
1974 | 1967 | // CPy-style methods |
1975 | 1968 | // TODO(fa) support static and class methods |
1976 | 1969 | PExternalFunctionWrapper sig = PExternalFunctionWrapper.fromMethodFlags(flags); |
1977 | | - RootCallTarget callTarget = PExternalFunctionWrapper.getOrCreateCallTarget(sig, PythonLanguage.get(inliningTarget), methodName, true, CExtContext.isMethStatic(flags)); |
| 1970 | + RootCallTarget callTarget = PExternalFunctionWrapper.getOrCreateCallTarget(sig, PythonLanguage.get(inliningTarget), methodName, CExtContext.isMethStatic(flags)); |
1978 | 1971 | mlMethObj = ensureCallableNode.execute(inliningTarget, mlMethObj, sig); |
1979 | 1972 | PKeyword[] kwDefaults = ExternalFunctionNodes.createKwDefaults(mlMethObj); |
1980 | 1973 | PBuiltinFunction function = PFactory.createBuiltinFunction(language, methodName, null, PythonUtils.EMPTY_OBJECT_ARRAY, kwDefaults, flags, callTarget); |
@@ -2055,165 +2048,6 @@ static void doOther(Object object) { |
2055 | 2048 | } |
2056 | 2049 | } |
2057 | 2050 |
|
2058 | | - @GenerateUncached |
2059 | | - @GenerateInline |
2060 | | - @GenerateCached(false) |
2061 | | - @ImportStatic({CApiGuards.class, PGuards.class}) |
2062 | | - public abstract static class CreateFunctionNode extends Node { |
2063 | | - |
2064 | | - private static final TruffleLogger LOGGER = CApiContext.getLogger(CreateFunctionNode.class); |
2065 | | - |
2066 | | - public static PythonObject executeUncached(TruffleString name, Object callable, int wrapper, Object type, Object flags) { |
2067 | | - return CreateFunctionNodeGen.getUncached().execute(null, name, callable, wrapper, type, flags); |
2068 | | - } |
2069 | | - |
2070 | | - public abstract PythonObject execute(Node inliningTarget, TruffleString name, Object callable, int wrapper, Object type, Object flags); |
2071 | | - |
2072 | | - /* |
2073 | | - * Note: this is called from PyTruffleType_AddSlot, which is similar to CPython's |
2074 | | - * add_operators: it creates corresponding Python magic methods from slots, but only from |
2075 | | - * slots declared on given native type and not from inherited slots. So we should not see |
2076 | | - * here pointers to native wrappers of managed slots. However, one could: 1) initialize a |
2077 | | - * type multiple times, in which case we'd see here inherited slots, or 2) "steal" a slot |
2078 | | - * from some existing type. This is why we resolve native closures and handle delegates of |
2079 | | - * type TpSlotBuiltin/Managed in the managed case. |
2080 | | - */ |
2081 | | - |
2082 | | - @Specialization(guards = "!isNoValue(type)") |
2083 | | - @TruffleBoundary |
2084 | | - static PythonObject doPythonCallable(TruffleString name, PythonNativeWrapper callable, int signature, Object type, int flags) { |
2085 | | - Object managedCallable = callable.getDelegate(); |
2086 | | - PythonContext context = PythonContext.get(null); |
2087 | | - PythonLanguage language = context.getLanguage(); |
2088 | | - boolean doArgAndResultConversion = false; |
2089 | | - if (managedCallable instanceof TpSlotBuiltin<?> builtinSlot) { |
2090 | | - var builtin = builtinSlot.createBuiltin(context, type, name, PExternalFunctionWrapper.fromValue(signature)); |
2091 | | - if (builtin != null) { |
2092 | | - return builtin; |
2093 | | - } |
2094 | | - assert callable instanceof TpSlotWrapper; |
2095 | | - managedCallable = callable; |
2096 | | - doArgAndResultConversion = true; |
2097 | | - } else if (managedCallable instanceof TpSlotPython pythonSlot) { |
2098 | | - // Someone has "stolen" existing python slot and stashed it into its slot field |
2099 | | - // See TpSlots#fromNative where we need to solve the same issue |
2100 | | - assert callable instanceof TpSlotWrapper; |
2101 | | - TpSlotPython newPythonSlot = pythonSlot.forNewType(type); |
2102 | | - if (newPythonSlot != pythonSlot) { |
2103 | | - managedCallable = ((TpSlotWrapper) callable).cloneWith(newPythonSlot); |
2104 | | - } else { |
2105 | | - managedCallable = callable; |
2106 | | - } |
2107 | | - doArgAndResultConversion = true; |
2108 | | - } |
2109 | | - PythonObject function = PExternalFunctionWrapper.createWrapperFunction(name, managedCallable, type, flags, signature, language, doArgAndResultConversion); |
2110 | | - return function != null ? function : castToPythonObject(managedCallable); |
2111 | | - } |
2112 | | - |
2113 | | - @Specialization |
2114 | | - @TruffleBoundary |
2115 | | - static PythonObject doPyCFunctionWrapper(TruffleString name, PyCFunctionWrapper wrapper, int signature, Object type, int flags) { |
2116 | | - Object delegate = wrapper.getDelegate(); |
2117 | | - assert !(delegate instanceof PythonAbstractObject); |
2118 | | - PythonContext context = PythonContext.get(null); |
2119 | | - PythonLanguage language = context.getLanguage(); |
2120 | | - return PExternalFunctionWrapper.createWrapperFunction(name, delegate, type, flags, signature, language, false); |
2121 | | - } |
2122 | | - |
2123 | | - @Specialization(guards = {"!isNativeWrapper(callable)"}) |
2124 | | - @TruffleBoundary |
2125 | | - static PythonObject doNativeCallableWithWrapper(TruffleString name, Object callable, int signature, Object type, int flags, |
2126 | | - @CachedLibrary(limit = "3") InteropLibrary lib) { |
2127 | | - PythonContext context = PythonContext.get(null); |
2128 | | - Object resolvedCallable = resolveClosurePointer(context, callable, lib); |
2129 | | - assert !(resolvedCallable instanceof TpSlotNative); |
2130 | | - if (resolvedCallable instanceof TpSlotBuiltin<?> builtinSlot) { |
2131 | | - // CPython also creates a new wrapper descriptor even for slots that already |
2132 | | - // have some wrapper descriptor. We can use the slot itself to create the right |
2133 | | - // descriptor avoiding the delegation |
2134 | | - var builtin = builtinSlot.createBuiltin(context, type, name, PExternalFunctionWrapper.fromValue(signature)); |
2135 | | - if (builtin != null) { |
2136 | | - return builtin; |
2137 | | - } |
2138 | | - // Otherwise fallback to wrapping the callable as if it was just opaque native call |
2139 | | - resolvedCallable = null; |
2140 | | - } else if (resolvedCallable instanceof TpSlotPython pythonSlot) { |
2141 | | - // Someone has "stolen" existing python slot and stashed it into its slot field |
2142 | | - // We will delegate to the native closure to be as compatible with whatever |
2143 | | - // native call trickery the user intends to do |
2144 | | - // Note: we do not have a simple way to write back the new slot if it changed, |
2145 | | - // so TpSlots#fromNative will do this again and will write back the new slot to the |
2146 | | - // PyTypeObject slot field |
2147 | | - TpSlotPython newSlot = pythonSlot.forNewType(type); |
2148 | | - try { |
2149 | | - Object wrapper = context.getCApiContext().getClosureExecutable(lib.asPointer(callable)); |
2150 | | - if (wrapper instanceof TpSlotWrapper slotWrapper) { |
2151 | | - TpSlotWrapper newWrapper = newSlot != pythonSlot ? slotWrapper.cloneWith(newSlot) : slotWrapper; |
2152 | | - newWrapper.toNative(SignatureLibrary.getUncached()); |
2153 | | - callable = context.getCApiContext().getClosureForExecutable(newWrapper); |
2154 | | - } |
2155 | | - resolvedCallable = null; |
2156 | | - } catch (UnsupportedMessageException ignore) { |
2157 | | - // resolveClosurePointer gave non-null result, it must be a pointer |
2158 | | - throw CompilerDirectives.shouldNotReachHere(); |
2159 | | - } |
2160 | | - } |
2161 | | - boolean doArgAndResultConversion; |
2162 | | - if (resolvedCallable != null) { |
2163 | | - doArgAndResultConversion = false; |
2164 | | - } else { |
2165 | | - doArgAndResultConversion = true; |
2166 | | - resolvedCallable = callable; |
2167 | | - } |
2168 | | - PythonLanguage language = context.getLanguage(); |
2169 | | - PythonObject function = PExternalFunctionWrapper.createWrapperFunction(name, resolvedCallable, type, flags, signature, language, doArgAndResultConversion); |
2170 | | - return function != null ? function : castToPythonObject(resolvedCallable); |
2171 | | - } |
2172 | | - |
2173 | | - private static PythonObject castToPythonObject(Object callable) { |
2174 | | - if (callable instanceof PythonObject pythonObject) { |
2175 | | - return pythonObject; |
2176 | | - } |
2177 | | - transferToInterpreterAndInvalidate(); |
2178 | | - throw shouldNotReachHere("Unexpected class of callable: " + callable.getClass()); |
2179 | | - } |
2180 | | - |
2181 | | - /** |
2182 | | - * If possible resolves the pointer to a {@link PBuiltinFunction} (creating a fresh builtin |
2183 | | - * from builtin slots). |
2184 | | - */ |
2185 | | - @TruffleBoundary |
2186 | | - public static Object resolveClosurePointerToBuiltinFun(PythonContext context, Object callable, InteropLibrary lib, |
2187 | | - Object type, TruffleString name, PExternalFunctionWrapper signature) { |
2188 | | - Object delegate = resolveClosurePointer(context, callable, lib); |
2189 | | - if (delegate instanceof TpSlotBuiltin<?> builtinSlot) { |
2190 | | - return builtinSlot.createBuiltin(context, type, name, signature); |
2191 | | - } |
2192 | | - return delegate; |
2193 | | - } |
2194 | | - |
2195 | | - /** |
2196 | | - * Returns either {@link PBuiltinFunction} or {@link TpSlotBuiltin}. |
2197 | | - */ |
2198 | | - @TruffleBoundary |
2199 | | - public static Object resolveClosurePointer(PythonContext context, Object callable, InteropLibrary lib) { |
2200 | | - if (lib.isPointer(callable)) { |
2201 | | - long pointer; |
2202 | | - try { |
2203 | | - pointer = lib.asPointer(callable); |
2204 | | - } catch (UnsupportedMessageException e) { |
2205 | | - throw shouldNotReachHere(e); |
2206 | | - } |
2207 | | - Object delegate = context.getCApiContext().getClosureDelegate(pointer); |
2208 | | - if (delegate != null) { |
2209 | | - LOGGER.fine(() -> PythonUtils.formatJString("resolved closure pointer %d 0x%x to %s", pointer, pointer, delegate)); |
2210 | | - return delegate; |
2211 | | - } |
2212 | | - } |
2213 | | - return null; |
2214 | | - } |
2215 | | - } |
2216 | | - |
2217 | 2051 | /** |
2218 | 2052 | * Similar to CPython's macro {@code Py_VISIT}, this node will call the provided visit function |
2219 | 2053 | * on the item if that item is a native object. This is because we assume that the traverse and |
|
0 commit comments