62
62
import com .oracle .graal .python .util .PythonUtils ;
63
63
import com .oracle .truffle .api .CallTarget ;
64
64
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
65
+ import com .oracle .truffle .api .CompilerDirectives .ValueType ;
65
66
import com .oracle .truffle .api .TruffleLanguage .Env ;
66
67
import com .oracle .truffle .api .interop .ArityException ;
67
68
import com .oracle .truffle .api .interop .InteropLibrary ;
@@ -159,17 +160,41 @@ public final DynamicObject getSymbolCache() {
159
160
160
161
protected abstract Store initializeSymbolCache ();
161
162
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
+
162
189
/**
163
190
* This method loads a C extension module (C API or HPy API) and will initialize the
164
191
* corresponding native contexts if necessary.
165
192
*
166
193
* @param location The node that's requesting this operation. This is required for reporting
167
194
* correct source code location in case exceptions occur.
168
195
* @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).
173
198
* @param checkFunctionResultNode An adopted node instance. This is necessary because the result
174
199
* check could raise an exception and only an adopted node will report useful source
175
200
* locations.
@@ -181,28 +206,27 @@ public final DynamicObject getSymbolCache() {
181
206
* @throws ImportException If an exception occurred during C extension initialization.
182
207
*/
183
208
@ 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 {
187
211
// 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 );
190
214
191
215
InteropLibrary llvmInteropLib = InteropLibrary .getUncached (llvmLibrary );
192
216
193
217
// Now, try to detect the C extension's API by looking for the appropriate init
194
218
// functions.
195
- String basename = name .substring (name .lastIndexOf ('.' ) + 1 );
219
+ String basename = spec . name .substring (spec . name .lastIndexOf ('.' ) + 1 );
196
220
String hpyInitFuncName = "HPyInit_" + basename ;
197
221
String initFuncName = "PyInit_" + basename ;
198
222
try {
199
223
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 );
202
226
}
203
- return cApiContext .initCApiModule (location , llvmLibrary , initFuncName , name , path , llvmInteropLib , checkFunctionResultNode );
227
+ return cApiContext .initCApiModule (location , llvmLibrary , initFuncName , spec , llvmInteropLib , checkFunctionResultNode );
204
228
} 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 , "" );
206
230
}
207
231
}
208
232
0 commit comments