40
40
*/
41
41
package com .oracle .graal .python .builtins .modules ;
42
42
43
- import static com .oracle .graal .python .nodes .SpecialAttributeNames .__FILE__ ;
44
43
import static com .oracle .graal .python .runtime .exception .PythonErrorType .NotImplementedError ;
45
44
46
45
import java .io .IOException ;
50
49
import com .oracle .graal .python .PythonLanguage ;
51
50
import com .oracle .graal .python .builtins .Builtin ;
52
51
import com .oracle .graal .python .builtins .CoreFunctions ;
52
+ import com .oracle .graal .python .builtins .Python3Core ;
53
+ import com .oracle .graal .python .builtins .PythonBuiltinClassType ;
53
54
import com .oracle .graal .python .builtins .PythonBuiltins ;
54
- import com .oracle .graal .python .builtins .modules .PythonCextBuiltinsFactory .DefaultCheckFunctionResultNodeGen ;
55
55
import com .oracle .graal .python .builtins .objects .PNone ;
56
56
import com .oracle .graal .python .builtins .objects .bytes .PBytes ;
57
57
import com .oracle .graal .python .builtins .objects .bytes .PBytesLike ;
58
+ import com .oracle .graal .python .builtins .objects .cext .capi .CExtNodes .ExecModuleNode ;
59
+ import com .oracle .graal .python .builtins .objects .cext .capi .DynamicObjectNativeWrapper ;
60
+ import com .oracle .graal .python .builtins .objects .cext .capi .ExternalFunctionNodesFactory .DefaultCheckFunctionResultNodeGen ;
61
+ import com .oracle .graal .python .builtins .objects .cext .capi .NativeMember ;
58
62
import com .oracle .graal .python .builtins .objects .cext .common .CExtCommonNodes .CheckFunctionResultNode ;
59
63
import com .oracle .graal .python .builtins .objects .cext .common .CExtContext ;
64
+ import com .oracle .graal .python .builtins .objects .cext .common .CExtContext .ModuleSpec ;
60
65
import com .oracle .graal .python .builtins .objects .cext .common .LoadCExtException .ApiInitException ;
61
66
import com .oracle .graal .python .builtins .objects .cext .common .LoadCExtException .ImportException ;
62
67
import com .oracle .graal .python .builtins .objects .cext .hpy .HPyExternalFunctionNodes .HPyCheckFunctionResultNode ;
63
68
import com .oracle .graal .python .builtins .objects .cext .hpy .HPyExternalFunctionNodesFactory .HPyCheckHandleResultNodeGen ;
64
69
import com .oracle .graal .python .builtins .objects .code .PCode ;
65
- import com .oracle .graal .python .builtins .objects .dict . PDict ;
70
+ import com .oracle .graal .python .builtins .objects .common . HashingStorageLibrary ;
66
71
import com .oracle .graal .python .builtins .objects .ints .IntBuiltins ;
67
72
import com .oracle .graal .python .builtins .objects .ints .PInt ;
68
73
import com .oracle .graal .python .builtins .objects .module .PythonModule ;
69
74
import com .oracle .graal .python .builtins .objects .object .PythonObject ;
70
75
import com .oracle .graal .python .builtins .objects .object .PythonObjectLibrary ;
71
76
import com .oracle .graal .python .builtins .objects .str .PString ;
72
- import com .oracle .graal .python .nodes .ErrorMessages ;
73
- import com .oracle .graal .python .nodes .PRaiseNode ;
74
77
import com .oracle .graal .python .nodes .attributes .ReadAttributeFromDynamicObjectNode ;
75
78
import com .oracle .graal .python .nodes .attributes .SetAttributeNode ;
76
79
import com .oracle .graal .python .nodes .function .PythonBuiltinBaseNode ;
81
84
import com .oracle .graal .python .runtime .ExecutionContext .IndirectCallContext ;
82
85
import com .oracle .graal .python .runtime .GilNode ;
83
86
import com .oracle .graal .python .runtime .PythonContext ;
84
- import com .oracle .graal .python .builtins .Python3Core ;
85
87
import com .oracle .graal .python .runtime .PythonOptions ;
86
- import com .oracle .graal .python .runtime .exception .PythonErrorType ;
87
88
import com .oracle .truffle .api .CompilerDirectives ;
88
89
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
89
90
import com .oracle .truffle .api .dsl .Cached ;
90
91
import com .oracle .truffle .api .dsl .CachedContext ;
91
92
import com .oracle .truffle .api .dsl .CachedLanguage ;
93
+ import com .oracle .truffle .api .dsl .Fallback ;
92
94
import com .oracle .truffle .api .dsl .GenerateNodeFactory ;
93
95
import com .oracle .truffle .api .dsl .NodeFactory ;
94
96
import com .oracle .truffle .api .dsl .Specialization ;
@@ -212,7 +214,7 @@ Object run(VirtualFrame frame, PythonObject moduleSpec, @SuppressWarnings("unuse
212
214
PythonContext context = getContext ();
213
215
Object state = IndirectCallContext .enter (frame , language , context , this );
214
216
try {
215
- return run (context , name , path );
217
+ return run (context , new ModuleSpec ( name , path , moduleSpec ) );
216
218
} catch (ApiInitException ie ) {
217
219
throw ie .reraise (getConstructAndRaiseNode (), frame );
218
220
} catch (ImportException ie ) {
@@ -225,29 +227,16 @@ Object run(VirtualFrame frame, PythonObject moduleSpec, @SuppressWarnings("unuse
225
227
}
226
228
227
229
@ TruffleBoundary
228
- private Object run (PythonContext context , String name , String path ) throws IOException , ApiInitException , ImportException {
229
-
230
- Object existingModule = findExtensionObject (name , path );
230
+ private Object run (PythonContext context , ModuleSpec spec ) throws IOException , ApiInitException , ImportException {
231
+ Object existingModule = findExtensionObject (spec );
231
232
if (existingModule != null ) {
232
233
return existingModule ;
233
234
}
234
-
235
- Object result = CExtContext .loadCExtModule (this , context , name , path , getCheckResultNode (), getCheckHPyResultNode ());
236
- if (!(result instanceof PythonModule )) {
237
- // PyModuleDef_Init(pyModuleDef)
238
- // TODO: PyModule_FromDefAndSpec((PyModuleDef*)m, spec);
239
- throw PRaiseNode .raiseUncached (this , PythonErrorType .NotImplementedError , ErrorMessages .MULTI_PHASE_INIT_OF_EXTENSION_MODULE_S , name );
240
- } else {
241
- ((PythonModule ) result ).setAttribute (__FILE__ , path );
242
- // TODO: _PyImport_FixupExtensionObject(result, name, path, sys.modules)
243
- PDict sysModules = context .getSysModules ();
244
- sysModules .setItem (name , result );
245
- return result ;
246
- }
235
+ return CExtContext .loadCExtModule (this , context , spec , getCheckResultNode (), getCheckHPyResultNode ());
247
236
}
248
237
249
238
@ SuppressWarnings ({"static-method" , "unused" })
250
- private Object findExtensionObject (String name , String path ) {
239
+ private Object findExtensionObject (ModuleSpec spec ) {
251
240
// TODO: to avoid initializing an extension module twice, keep an internal dict
252
241
// and possibly return from there, i.e., _PyImport_FindExtensionObject(name, path)
253
242
return null ;
@@ -270,13 +259,52 @@ private HPyCheckFunctionResultNode getCheckHPyResultNode() {
270
259
}
271
260
}
272
261
273
- @ Builtin (name = "exec_dynamic" , minNumOfPositionalArgs = 1 )
262
+ @ Builtin (name = "exec_dynamic" , minNumOfPositionalArgs = 1 , doc = "exec_dynamic($module, mod, /) \n -- \n \n Initialize an extension module." )
274
263
@ GenerateNodeFactory
275
264
public abstract static class ExecDynamicNode extends PythonBuiltinNode {
276
265
@ Specialization
277
- public Object run (PythonModule extensionModule ) {
278
- // TODO: implement PyModule_ExecDef
279
- return extensionModule ;
266
+ int doPythonModule (VirtualFrame frame , PythonModule extensionModule ,
267
+ @ CachedLanguage PythonLanguage language ,
268
+ @ CachedLibrary (limit = "1" ) HashingStorageLibrary lib ,
269
+ @ Cached ExecModuleNode execModuleNode ) {
270
+ Object nativeModuleDef = extensionModule .getNativeModuleDef ();
271
+ if (nativeModuleDef == null ) {
272
+ return 0 ;
273
+ }
274
+
275
+ /*
276
+ * Check if module is already initialized. CPython does that by testing if 'md_state !=
277
+ * NULL'. So, we do the same. Currently, we store this in the generic storage of the
278
+ * native wrapper.
279
+ */
280
+ DynamicObjectNativeWrapper nativeWrapper = extensionModule .getNativeWrapper ();
281
+ if (nativeWrapper != null && nativeWrapper .getNativeMemberStore () != null ) {
282
+ Object item = lib .getItem (nativeWrapper .getNativeMemberStore (), NativeMember .MD_STATE .getMemberName ());
283
+ if (item != PNone .NO_VALUE ) {
284
+ return 0 ;
285
+ }
286
+ }
287
+
288
+ PythonContext context = getContext ();
289
+ if (!context .hasCApiContext ()) {
290
+ throw raise (PythonBuiltinClassType .SystemError , "C API not yet initialized" );
291
+ }
292
+
293
+ /*
294
+ * ExecModuleNode will run the module definition's exec function which may run arbitrary
295
+ * C code. So we need to setup an indirect call.
296
+ */
297
+ Object state = IndirectCallContext .enter (frame , language , context , this );
298
+ try {
299
+ return execModuleNode .execute (context .getCApiContext (), extensionModule , nativeModuleDef );
300
+ } finally {
301
+ IndirectCallContext .exit (frame , language , context , state );
302
+ }
303
+ }
304
+
305
+ @ Fallback
306
+ static int doOther (@ SuppressWarnings ("unused" ) Object extensionModule ) {
307
+ return 0 ;
280
308
}
281
309
}
282
310
0 commit comments