Skip to content

Commit c4c0357

Browse files
committed
Pass through original ModuleSpec object
1 parent bab16f9 commit c4c0357

File tree

4 files changed

+63
-43
lines changed

4 files changed

+63
-43
lines changed

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

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import com.oracle.graal.python.builtins.objects.cext.capi.ExternalFunctionNodesFactory.DefaultCheckFunctionResultNodeGen;
6161
import com.oracle.graal.python.builtins.objects.cext.common.CExtCommonNodes.CheckFunctionResultNode;
6262
import com.oracle.graal.python.builtins.objects.cext.common.CExtContext;
63+
import com.oracle.graal.python.builtins.objects.cext.common.CExtContext.ModuleSpec;
6364
import com.oracle.graal.python.builtins.objects.cext.common.LoadCExtException.ApiInitException;
6465
import com.oracle.graal.python.builtins.objects.cext.common.LoadCExtException.ImportException;
6566
import com.oracle.graal.python.builtins.objects.cext.hpy.HPyExternalFunctionNodes.HPyCheckFunctionResultNode;
@@ -215,7 +216,7 @@ Object run(VirtualFrame frame, PythonObject moduleSpec, @SuppressWarnings("unuse
215216
PythonContext context = getContext();
216217
Object state = IndirectCallContext.enter(frame, language, context, this);
217218
try {
218-
return run(context, name, path);
219+
return run(context, new ModuleSpec(name, path, moduleSpec));
219220
} catch (ApiInitException ie) {
220221
throw ie.reraise(getConstructAndRaiseNode(), frame);
221222
} catch (ImportException ie) {
@@ -228,29 +229,29 @@ Object run(VirtualFrame frame, PythonObject moduleSpec, @SuppressWarnings("unuse
228229
}
229230

230231
@TruffleBoundary
231-
private Object run(PythonContext context, String name, String path) throws IOException, ApiInitException, ImportException {
232+
private Object run(PythonContext context, ModuleSpec spec) throws IOException, ApiInitException, ImportException {
232233

233-
Object existingModule = findExtensionObject(name, path);
234+
Object existingModule = findExtensionObject(spec);
234235
if (existingModule != null) {
235236
return existingModule;
236237
}
237238

238-
Object result = CExtContext.loadCExtModule(this, context, name, path, getCheckResultNode(), getCheckHPyResultNode());
239+
Object result = CExtContext.loadCExtModule(this, context, spec, getCheckResultNode(), getCheckHPyResultNode());
239240
if (!(result instanceof PythonModule)) {
240241
// PyModuleDef_Init(pyModuleDef)
241242
// TODO: PyModule_FromDefAndSpec((PyModuleDef*)m, spec);
242-
throw PRaiseNode.raiseUncached(this, PythonErrorType.NotImplementedError, ErrorMessages.MULTI_PHASE_INIT_OF_EXTENSION_MODULE_S, name);
243+
throw PRaiseNode.raiseUncached(this, PythonErrorType.NotImplementedError, ErrorMessages.MULTI_PHASE_INIT_OF_EXTENSION_MODULE_S, spec.name);
243244
} else {
244-
((PythonModule) result).setAttribute(__FILE__, path);
245+
((PythonModule) result).setAttribute(__FILE__, spec.path);
245246
// TODO: _PyImport_FixupExtensionObject(result, name, path, sys.modules)
246247
PDict sysModules = context.getSysModules();
247-
sysModules.setItem(name, result);
248+
sysModules.setItem(spec.name, result);
248249
return result;
249250
}
250251
}
251252

252253
@SuppressWarnings({"static-method", "unused"})
253-
private Object findExtensionObject(String name, String path) {
254+
private Object findExtensionObject(ModuleSpec spec) {
254255
// TODO: to avoid initializing an extension module twice, keep an internal dict
255256
// and possibly return from there, i.e., _PyImport_FindExtensionObject(name, path)
256257
return null;

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

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,9 @@
5454
import java.util.Objects;
5555
import java.util.logging.Level;
5656

57-
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodesFactory.CreateModuleNodeGen;
5857
import org.graalvm.collections.EconomicMap;
5958

6059
import com.oracle.graal.python.PythonLanguage;
61-
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
6260
import com.oracle.graal.python.builtins.modules.PythonCextBuiltins;
6361
import com.oracle.graal.python.builtins.objects.PNone;
6462
import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject;
@@ -67,6 +65,7 @@
6765
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.GetRefCntNode;
6866
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.PCallCapiFunction;
6967
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodesFactory.AsPythonObjectNodeGen;
68+
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodesFactory.CreateModuleNodeGen;
7069
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodesFactory.ResolveHandleNodeGen;
7170
import com.oracle.graal.python.builtins.objects.cext.capi.DynamicObjectNativeWrapper.PrimitiveNativeWrapper;
7271
import com.oracle.graal.python.builtins.objects.cext.capi.NativeObjectReferenceArrayWrapper.PointerArrayWrapper;
@@ -81,7 +80,6 @@
8180
import com.oracle.graal.python.builtins.objects.function.PArguments;
8281
import com.oracle.graal.python.builtins.objects.function.Signature;
8382
import com.oracle.graal.python.builtins.objects.module.PythonModule;
84-
import com.oracle.graal.python.builtins.objects.object.PythonObject;
8583
import com.oracle.graal.python.nodes.ErrorMessages;
8684
import com.oracle.graal.python.nodes.IndirectCallNode;
8785
import com.oracle.graal.python.nodes.PRootNode;
@@ -96,7 +94,6 @@
9694
import com.oracle.graal.python.runtime.PythonContext.PythonThreadState;
9795
import com.oracle.graal.python.runtime.PythonOptions;
9896
import com.oracle.graal.python.runtime.exception.PException;
99-
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
10097
import com.oracle.graal.python.util.PythonUtils;
10198
import com.oracle.truffle.api.CompilerAsserts;
10299
import com.oracle.truffle.api.CompilerDirectives;
@@ -936,15 +933,14 @@ public static CApiContext ensureCapiWasLoaded(Node node, PythonContext context,
936933
}
937934

938935
@TruffleBoundary
939-
public Object initCApiModule(Node location, Object llvmLibrary, String initFuncName, String name, String path,
940-
InteropLibrary llvmInteropLib,
941-
CheckFunctionResultNode checkFunctionResultNode) throws UnsupportedMessageException, ArityException, UnsupportedTypeException, ImportException {
936+
public Object initCApiModule(Node location, Object llvmLibrary, String initFuncName, ModuleSpec spec, InteropLibrary llvmInteropLib, CheckFunctionResultNode checkFunctionResultNode)
937+
throws UnsupportedMessageException, ArityException, UnsupportedTypeException, ImportException {
942938
PythonContext context = getContext();
943939
Object pyinitFunc;
944940
try {
945941
pyinitFunc = llvmInteropLib.readMember(llvmLibrary, initFuncName);
946942
} catch (UnknownIdentifierException | UnsupportedMessageException e1) {
947-
throw new ImportException(null, name, path, ErrorMessages.NO_FUNCTION_FOUND, "", initFuncName, path);
943+
throw new ImportException(null, spec.name, spec.path, ErrorMessages.NO_FUNCTION_FOUND, "", initFuncName, spec.path);
948944
}
949945
InteropLibrary pyInitFuncLib = InteropLibrary.getUncached(pyinitFunc);
950946
Object nativeResult;
@@ -963,16 +959,12 @@ public Object initCApiModule(Node location, Object llvmLibrary, String initFuncN
963959
Object result = AsPythonObjectNodeGen.getUncached().execute(ResolveHandleNodeGen.getUncached().execute(nativeResult));
964960
if (!(result instanceof PythonModule)) {
965961
// Multi-phase extension module initialization
966-
// TOOD: pass through module spec
967-
PythonObject moduleSpec = PythonObjectFactory.getUncached().createPythonObject(PythonBuiltinClassType.PythonObject);
968-
moduleSpec.setAttribute("name", name);
969-
moduleSpec.setAttribute("origin", path);
970-
return CreateModuleNodeGen.getUncached().execute(context.getCApiContext(), moduleSpec, result);
962+
return CreateModuleNodeGen.getUncached().execute(context.getCApiContext(), spec, result);
971963
} else {
972-
((PythonModule) result).setAttribute(__FILE__, path);
964+
((PythonModule) result).setAttribute(__FILE__, spec.path);
973965
// TODO: _PyImport_FixupExtensionObject(result, name, path, sys.modules)
974966
PDict sysModules = context.getSysModules();
975-
sysModules.setItem(name, result);
967+
sysModules.setItem(spec.name, result);
976968
return result;
977969
}
978970
}

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

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@
112112
import com.oracle.graal.python.builtins.objects.cext.common.CExtCommonNodes.ConvertPIntToPrimitiveNode;
113113
import com.oracle.graal.python.builtins.objects.cext.common.CExtCommonNodes.ImportCExtSymbolNode;
114114
import com.oracle.graal.python.builtins.objects.cext.common.CExtContext;
115+
import com.oracle.graal.python.builtins.objects.cext.common.CExtContext.ModuleSpec;
115116
import com.oracle.graal.python.builtins.objects.cext.common.CExtToJavaNode;
116117
import com.oracle.graal.python.builtins.objects.cext.common.CExtToNativeNode;
117118
import com.oracle.graal.python.builtins.objects.cext.common.GetVaArgsNode;
@@ -3611,10 +3612,10 @@ static boolean checkLayout(Object moduleDef, InteropLibrary moduleDefLib) {
36113612
return true;
36123613
}
36133614

3614-
public abstract Object execute(CApiContext capiContext, Object moduleSpec, Object moduleDef);
3615+
public abstract Object execute(CApiContext capiContext, ModuleSpec moduleSpec, Object moduleDef);
36153616

36163617
@Specialization
3617-
static Object doGeneric(CApiContext capiContext, Object moduleSpec, PythonAbstractNativeObject moduleDefWrapper,
3618+
static Object doGeneric(CApiContext capiContext, ModuleSpec moduleSpec, PythonAbstractNativeObject moduleDefWrapper,
36183619
@CachedLanguage PythonLanguage language,
36193620
@Cached PythonObjectFactory factory,
36203621
@Cached GetSulongTypeNode getSulongTypeNode,
@@ -3635,12 +3636,14 @@ static Object doGeneric(CApiContext capiContext, Object moduleSpec, PythonAbstra
36353636

36363637
assert checkLayout(moduleDef, interopLib);
36373638

3638-
String mName;
3639+
/*
3640+
* The name of the module is taken from the module spec and *NOT* from the module
3641+
* definition.
3642+
*/
3643+
String mName = moduleSpec.name;
36393644
Object mDoc;
36403645
int mSize;
36413646
try {
3642-
mName = castToJavaStringNode.execute(fromCharPointerNode.execute(interopLib.readMember(moduleDef, M_NAME)));
3643-
36443647
// do not eagerly read the doc string; this turned out to be unnecessarily expensive
36453648
mDoc = fromCharPointerNode.execute(interopLib.readMember(moduleDef, M_DOC));
36463649

@@ -3692,7 +3695,7 @@ static Object doGeneric(CApiContext capiContext, Object moduleSpec, PythonAbstra
36923695

36933696
Object module;
36943697
if (createFunction != null && !interopLib.isNull(createFunction)) {
3695-
Object[] cArguments = new Object[]{moduleSpecToNativeNode.execute(capiContext, moduleSpec), moduleDef};
3698+
Object[] cArguments = new Object[]{moduleSpecToNativeNode.execute(capiContext, moduleSpec.originalModuleSpec), moduleDef};
36963699
try {
36973700
Object result = interopLib.execute(createFunction, cArguments);
36983701
DefaultCheckFunctionResultNode.checkFunctionResult(mName, interopLib.isNull(result), false, language, capiContext.getContext(), raiseNode, factory,

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

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import com.oracle.graal.python.util.PythonUtils;
6363
import com.oracle.truffle.api.CallTarget;
6464
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
65+
import com.oracle.truffle.api.CompilerDirectives.ValueType;
6566
import com.oracle.truffle.api.TruffleLanguage.Env;
6667
import com.oracle.truffle.api.interop.ArityException;
6768
import com.oracle.truffle.api.interop.InteropLibrary;
@@ -159,17 +160,41 @@ public final DynamicObject getSymbolCache() {
159160

160161
protected abstract Store initializeSymbolCache();
161162

163+
/**
164+
* A simple helper object that just remembers the name and the path of the original module spec
165+
* object and also keeps a reference to it. This should avoid redundant attribute reads.
166+
*/
167+
@ValueType
168+
public static final class ModuleSpec {
169+
/**
170+
* The name of the module to load (also just required for creating appropriate error
171+
* messages).
172+
*/
173+
public final String name;
174+
175+
/**
176+
* The path of the C extension module to load (usually something ending with {@code .so} or
177+
* {@code .dylib} or similar).
178+
*/
179+
public final String path;
180+
public final Object originalModuleSpec;
181+
182+
public ModuleSpec(String name, String path, Object originalModuleSpec) {
183+
this.name = name;
184+
this.path = path;
185+
this.originalModuleSpec = originalModuleSpec;
186+
}
187+
}
188+
162189
/**
163190
* This method loads a C extension module (C API or HPy API) and will initialize the
164191
* corresponding native contexts if necessary.
165192
*
166193
* @param location The node that's requesting this operation. This is required for reporting
167194
* correct source code location in case exceptions occur.
168195
* @param context The Python context object.
169-
* @param name The name of the module to load (also just required for creating appropriate error
170-
* messages).
171-
* @param path The path of the C extension module to load (usually something ending with
172-
* {@code .so} or {@code .dylib} or similar).
196+
* @param spec The name and path of the module (also containing the original module spec
197+
* object).
173198
* @param checkFunctionResultNode An adopted node instance. This is necessary because the result
174199
* check could raise an exception and only an adopted node will report useful source
175200
* locations.
@@ -181,28 +206,27 @@ public final DynamicObject getSymbolCache() {
181206
* @throws ImportException If an exception occurred during C extension initialization.
182207
*/
183208
@TruffleBoundary
184-
public static Object loadCExtModule(Node location, PythonContext context, String name, String path,
185-
CheckFunctionResultNode checkFunctionResultNode,
186-
HPyCheckFunctionResultNode checkHPyResultNode) throws IOException, ApiInitException, ImportException {
209+
public static Object loadCExtModule(Node location, PythonContext context, ModuleSpec spec, CheckFunctionResultNode checkFunctionResultNode, HPyCheckFunctionResultNode checkHPyResultNode)
210+
throws IOException, ApiInitException, ImportException {
187211
// we always need to load the CPython C API (even for HPy modules)
188-
CApiContext cApiContext = CApiContext.ensureCapiWasLoaded(location, context, name, path);
189-
Object llvmLibrary = loadLLVMLibrary(location, context, name, path);
212+
CApiContext cApiContext = CApiContext.ensureCapiWasLoaded(location, context, spec.name, spec.path);
213+
Object llvmLibrary = loadLLVMLibrary(location, context, spec.name, spec.path);
190214

191215
InteropLibrary llvmInteropLib = InteropLibrary.getUncached(llvmLibrary);
192216

193217
// Now, try to detect the C extension's API by looking for the appropriate init
194218
// functions.
195-
String basename = name.substring(name.lastIndexOf('.') + 1);
219+
String basename = spec.name.substring(spec.name.lastIndexOf('.') + 1);
196220
String hpyInitFuncName = "HPyInit_" + basename;
197221
String initFuncName = "PyInit_" + basename;
198222
try {
199223
if (llvmInteropLib.isMemberExisting(llvmLibrary, hpyInitFuncName)) {
200-
GraalHPyContext hpyContext = GraalHPyContext.ensureHPyWasLoaded(location, context, name, path);
201-
return hpyContext.initHPyModule(context, llvmLibrary, hpyInitFuncName, name, path, false, llvmInteropLib, checkHPyResultNode);
224+
GraalHPyContext hpyContext = GraalHPyContext.ensureHPyWasLoaded(location, context, spec.name, spec.path);
225+
return hpyContext.initHPyModule(context, llvmLibrary, hpyInitFuncName, spec.name, spec.path, false, llvmInteropLib, checkHPyResultNode);
202226
}
203-
return cApiContext.initCApiModule(location, llvmLibrary, initFuncName, name, path, llvmInteropLib, checkFunctionResultNode);
227+
return cApiContext.initCApiModule(location, llvmLibrary, initFuncName, spec, llvmInteropLib, checkFunctionResultNode);
204228
} catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) {
205-
throw new ImportException(CExtContext.wrapJavaException(e, location), name, path, ErrorMessages.CANNOT_INITIALIZE_WITH, path, basename, "");
229+
throw new ImportException(CExtContext.wrapJavaException(e, location), spec.name, spec.path, ErrorMessages.CANNOT_INITIALIZE_WITH, spec.path, basename, "");
206230
}
207231
}
208232

0 commit comments

Comments
 (0)