Skip to content

Commit 5d4f088

Browse files
committed
CTypes can fallback to LLVM only when python.NativeModules=false
1 parent 82ba503 commit 5d4f088

File tree

2 files changed

+22
-50
lines changed

2 files changed

+22
-50
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/CtypesModuleBuiltins.java

Lines changed: 18 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,12 @@
102102
import com.oracle.graal.python.builtins.modules.PosixModuleBuiltins.FsConverterNode;
103103
import com.oracle.graal.python.builtins.modules.SysModuleBuiltins.AuditNode;
104104
import com.oracle.graal.python.builtins.modules.ctypes.CFieldBuiltins.GetFuncNode;
105+
import com.oracle.graal.python.builtins.modules.ctypes.CtypesModuleBuiltinsClinicProviders.DyldSharedCacheContainsPathClinicProviderGen;
105106
import com.oracle.graal.python.builtins.modules.ctypes.CtypesNodes.PyTypeCheck;
106107
import com.oracle.graal.python.builtins.modules.ctypes.FFIType.FFI_TYPES;
107108
import com.oracle.graal.python.builtins.modules.ctypes.FFIType.FieldGet;
108109
import com.oracle.graal.python.builtins.modules.ctypes.StgDictBuiltins.PyObjectStgDictNode;
109110
import com.oracle.graal.python.builtins.modules.ctypes.StgDictBuiltins.PyTypeStgDictNode;
110-
import com.oracle.graal.python.builtins.modules.ctypes.CtypesModuleBuiltinsClinicProviders.DyldSharedCacheContainsPathClinicProviderGen;
111111
import com.oracle.graal.python.builtins.modules.ctypes.memory.Pointer;
112112
import com.oracle.graal.python.builtins.modules.ctypes.memory.PointerNodes;
113113
import com.oracle.graal.python.builtins.modules.ctypes.memory.PointerReference;
@@ -131,7 +131,6 @@
131131
import com.oracle.graal.python.builtins.objects.dict.PDict;
132132
import com.oracle.graal.python.builtins.objects.function.PKeyword;
133133
import com.oracle.graal.python.builtins.objects.module.PythonModule;
134-
import com.oracle.graal.python.builtins.objects.str.StringBuiltins.PrefixSuffixNode;
135134
import com.oracle.graal.python.builtins.objects.str.StringUtils.SimpleTruffleStringFormatNode;
136135
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
137136
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetBaseClassNode;
@@ -204,7 +203,6 @@
204203
import com.oracle.truffle.api.nodes.Node;
205204
import com.oracle.truffle.api.source.Source;
206205
import com.oracle.truffle.api.strings.TruffleString;
207-
import com.oracle.truffle.api.strings.TruffleString.CodePointLengthNode;
208206
import com.oracle.truffle.api.strings.TruffleString.EqualNode;
209207
import com.oracle.truffle.api.strings.TruffleStringBuilder;
210208
import com.oracle.truffle.nfi.api.SignatureLibrary;
@@ -226,8 +224,6 @@ protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFa
226224

227225
private DLHandler rtldDefault;
228226
private Object dyldSharedCacheContainsPathFunction;
229-
@CompilationFinal private Object strlenFunction;
230-
@CompilationFinal private Object memcpyFunction;
231227

232228
protected static final int FUNCFLAG_STDCALL = 0x0;
233229
protected static final int FUNCFLAG_CDECL = 0x1;
@@ -272,22 +268,23 @@ public void postInitialize(Python3Core core) {
272268

273269
PythonContext context = core.getContext();
274270

275-
DLHandler handle;
271+
DLHandler handle = null;
272+
// We use directly native if available
276273
if (context.getEnv().isNativeAccessAllowed()) {
277274
handle = DlOpenNode.loadNFILibrary(context, NFIBackend.NATIVE, J_DEFAULT_LIBRARY, rtldLocal);
278-
setCtypeNFIHelpers(this, context, handle);
279-
280275
if (PythonOS.getPythonOS() == PythonOS.PLATFORM_WIN32) {
281276
PythonModule sysModule = context.getSysModule();
282277
Object loadLibraryMethod = ReadAttributeFromObjectNode.getUncached().execute(ctypesModule, toTruffleStringUncached("LoadLibrary"));
283278
Object pythonLib = CallNode.executeUncached(loadLibraryMethod, toTruffleStringUncached(GraalHPyJNIContext.getJNILibrary()), 0);
284279
WriteAttributeToPythonObjectNode.getUncached().execute(sysModule, toTruffleStringUncached("dllhandle"), pythonLib);
285280
}
286-
} else {
281+
} else if (!PythonOptions.NativeModules.getValue(context.getEnv().getOptions())) {
282+
// If native is not available, we can use the C API support library only if it was
283+
// loaded through LLVM and not NFI. This limitation can be lifted: we can reload the
284+
// library with LLVM here.
287285
try {
288286
Object llvmLibrary = CApiContext.ensureCApiLLVMLibrary(context);
289287
handle = new DLHandler(llvmLibrary, 0, J_EMPTY_STRING, true);
290-
setCtypeLLVMHelpers(this, handle);
291288
} catch (ApiInitException e) {
292289
throw e.reraise(null, null, PConstructAndRaiseNode.Lazy.getUncached());
293290
} catch (ImportException e) {
@@ -296,38 +293,16 @@ public void postInitialize(Python3Core core) {
296293
throw PConstructAndRaiseNode.getUncached().raiseOSError(null, e, EqualNode.getUncached());
297294
}
298295
}
299-
NativeFunction memmove = MemMoveFunction.create(handle, context);
300-
ctypesModule.setAttribute(tsLiteral("_memmove_addr"), factory.createNativeVoidPtr(memmove, memmove.adr));
301-
NativeFunction memset = MemSetFunction.create(handle, context);
302-
ctypesModule.setAttribute(tsLiteral("_memset_addr"), factory.createNativeVoidPtr(memset, memset.adr));
303-
rtldDefault = handle;
304-
}
305-
306-
Object getStrlenFunction() {
307-
return strlenFunction;
308-
}
309-
310-
Object getMemcpyFunction() {
311-
return memcpyFunction;
312-
}
313-
314-
private static void setCtypeLLVMHelpers(CtypesModuleBuiltins ctypesModuleBuiltins, DLHandler h) {
315-
try {
316-
InteropLibrary lib = InteropLibrary.getUncached(h.library);
317-
ctypesModuleBuiltins.strlenFunction = lib.readMember(h.library, NativeCAPISymbol.FUN_STRLEN.getName());
318-
ctypesModuleBuiltins.memcpyFunction = lib.readMember(h.library, NativeCAPISymbol.FUN_MEMCPY.getName());
319-
} catch (UnsupportedMessageException | UnknownIdentifierException e) {
320-
throw CompilerDirectives.shouldNotReachHere();
321-
}
322-
}
323-
324-
private static void setCtypeNFIHelpers(CtypesModuleBuiltins ctypesModuleBuiltins, PythonContext context, DLHandler h) {
325-
try {
326-
ctypesModuleBuiltins.strlenFunction = createNFIHelperFunction(context, h, "strlen", "(POINTER):UINT32");
327-
ctypesModuleBuiltins.memcpyFunction = createNFIHelperFunction(context, h, "memcpy", "([UINT8], POINTER, UINT32):POINTER");
328-
} catch (UnsupportedMessageException | UnknownIdentifierException e) {
329-
throw CompilerDirectives.shouldNotReachHere();
296+
if (handle != null) {
297+
NativeFunction memmove = MemMoveFunction.create(handle, context);
298+
ctypesModule.setAttribute(tsLiteral("_memmove_addr"), factory.createNativeVoidPtr(memmove, memmove.adr));
299+
NativeFunction memset = MemSetFunction.create(handle, context);
300+
ctypesModule.setAttribute(tsLiteral("_memset_addr"), factory.createNativeVoidPtr(memset, memset.adr));
330301
}
302+
// If handle == null, and we don't set the attributes, ctypes module is going to fail in
303+
// __init__.py on importing those attributes from _ctypes. This way the failure will happen
304+
// only when ctypes are actually imported
305+
rtldDefault = handle;
331306
}
332307

333308
@TruffleBoundary
@@ -734,8 +709,6 @@ static Object py_dl_open(VirtualFrame frame, PythonModule self, TruffleString na
734709
@Bind("this") Node inliningTarget,
735710
@Cached PyObjectHashNode hashNode,
736711
@Cached AuditNode auditNode,
737-
@Cached CodePointLengthNode codePointLengthNode,
738-
@Cached PrefixSuffixNode prefixSuffixNode,
739712
@Cached EqualNode eqNode,
740713
@Cached PythonObjectFactory factory,
741714
@Cached PRaiseNode.Lazy raiseNode) {
@@ -752,17 +725,14 @@ static Object py_dl_open(VirtualFrame frame, PythonModule self, TruffleString na
752725
PythonContext context = PythonContext.get(inliningTarget);
753726
DLHandler handle;
754727
Exception exception = null;
755-
boolean loadWithLLVM = !context.getEnv().isNativeAccessAllowed() || //
756-
(!context.getOption(PythonOptions.UseSystemToolchain) &&
757-
prefixSuffixNode.endsWith(name, context.getSoAbi(), 0, codePointLengthNode.execute(name, TS_ENCODING)));
758728
try {
759-
if (loadWithLLVM) {
729+
if (!context.getEnv().isNativeAccessAllowed() && !PythonOptions.NativeModules.getValue(context.getEnv().getOptions())) {
760730
Object handler = loadLLVMLibrary(context, inliningTarget, name);
761731
long adr = hashNode.execute(frame, inliningTarget, handler);
762732
handle = new DLHandler(handler, adr, name.toJavaStringUncached(), true);
763733
registerAddress(context, handle.adr, handle);
764734
return factory.createNativeVoidPtr(handle);
765-
} else {
735+
} else if (context.getEnv().isNativeAccessAllowed()) {
766736
CtypesThreadState ctypes = CtypesThreadState.get(context, PythonLanguage.get(inliningTarget));
767737
/*-
768738
TODO: (mq) cryptography in macos isn't always compatible with ctypes.

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@
114114
import com.oracle.graal.python.runtime.PythonOptions;
115115
import com.oracle.graal.python.runtime.exception.PException;
116116
import com.oracle.graal.python.util.Function;
117-
import com.oracle.graal.python.util.PythonUtils;
118117
import com.oracle.graal.python.util.PythonSystemThreadTask;
118+
import com.oracle.graal.python.util.PythonUtils;
119119
import com.oracle.graal.python.util.Supplier;
120120
import com.oracle.graal.python.util.SuppressFBWarnings;
121121
import com.oracle.graal.python.util.WeakIdentityHashMap;
@@ -798,7 +798,9 @@ public static CApiContext ensureCapiWasLoaded(String reason) {
798798

799799
@TruffleBoundary
800800
public static Object ensureCApiLLVMLibrary(PythonContext context) throws IOException, ImportException, ApiInitException {
801-
CApiContext cApiContext = ensureCapiWasLoaded(null, context, T_EMPTY_STRING, T_EMPTY_STRING, " load LLVM library (this is an internal bug)");
801+
assert !PythonOptions.NativeModules.getValue(context.getEnv().getOptions());
802+
CApiContext cApiContext = ensureCapiWasLoaded(null, context, T_EMPTY_STRING, T_EMPTY_STRING,
803+
" load LLVM library (this is an internal bug, LLVM library should not be loaded when running on native backend)");
802804
return cApiContext.getLLVMLibrary();
803805
}
804806

0 commit comments

Comments
 (0)