this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include "under-imp-module.h"
3
4#include "builtins-module.h"
5#include "builtins.h"
6#include "capi.h"
7#include "frame.h"
8#include "globals.h"
9#include "marshal.h"
10#include "module-builtins.h"
11#include "modules.h"
12#include "objects.h"
13#include "os.h"
14#include "runtime.h"
15#include "str-builtins.h"
16
17namespace py {
18
19static Thread* import_lock_holder;
20static word import_lock_count;
21
22void importAcquireLock(Thread* thread) {
23 if (import_lock_holder == nullptr) {
24 import_lock_holder = thread;
25 DCHECK(import_lock_count == 0, "count should be zero");
26 }
27 if (import_lock_holder == thread) {
28 ++import_lock_count;
29 } else {
30 UNIMPLEMENTED("builtinImpAcquireLock(): thread switching not implemented");
31 }
32}
33
34bool importReleaseLock(Thread* thread) {
35 if (import_lock_holder != thread) {
36 return false;
37 }
38 DCHECK(import_lock_count > 0, "count should be bigger than zero");
39 --import_lock_count;
40 if (import_lock_count == 0) {
41 import_lock_holder = nullptr;
42 }
43 return true;
44}
45
46RawObject FUNC(_imp, _import_fastpath)(Thread* thread, Arguments args) {
47 // This functions attempts to shortcut the import mechanics for modules that
48 // have already been loaded. It is called directly from
49 // _frozen_import_lib.__import__ and reproduces the functionality for the
50 // case when the module is present in sys.modules.
51 HandleScope scope(thread);
52 Object level(&scope, args.get(2));
53 // Only handle top level imports to avoid doing import name resolution.
54 if (level != SmallInt::fromWord(0)) {
55 return NoneType::object();
56 }
57 Object name(&scope, args.get(0));
58 if (!name.isStr()) {
59 return NoneType::object();
60 }
61 Str name_str(&scope, *name);
62 Runtime* runtime = thread->runtime();
63
64 Object result(&scope, runtime->findModule(name_str));
65 if (!result.isModule()) {
66 return NoneType::object();
67 }
68
69 // For imports with the style `from module import x,y,z` we need to verify
70 // that x, y, and z have all been loaded. This is the same checks as in
71 // _frozen_importlib._handle_fromlist.
72 Object fromlist_obj(&scope, args.get(1));
73 if (!fromlist_obj.isNoneType()) {
74 word fromlist_length;
75 if (fromlist_obj.isList()) {
76 fromlist_length = List::cast(*fromlist_obj).numItems();
77 fromlist_obj = List::cast(*fromlist_obj).items();
78 } else if (fromlist_obj.isTuple()) {
79 fromlist_length = Tuple::cast(*fromlist_obj).length();
80 } else {
81 return NoneType::object();
82 }
83 Tuple fromlist(&scope, *fromlist_obj);
84
85 if (fromlist_length > 0) {
86 Module module(&scope, *result);
87 Object attribute_name(&scope, NoneType::object());
88 Object attribute(&scope, NoneType::object());
89 for (word i = 0; i < fromlist_length; i++) {
90 attribute_name = fromlist.at(i);
91 if (!attribute_name.isStr()) {
92 return NoneType::object();
93 }
94 attribute_name = Runtime::internStr(thread, attribute_name);
95 attribute = moduleAt(module, attribute_name);
96 if (attribute.isErrorNotFound()) {
97 return NoneType::object();
98 }
99 }
100 return *result;
101 }
102 }
103 // If fromlist is empty return the top level package.
104 // ie: `__import__("module.x")` will return `module`
105 word index = strFindAsciiChar(name_str, '.');
106 if (index == -1) {
107 return *result;
108 }
109 name = strSubstr(thread, name_str, 0, index);
110 result = runtime->findModule(name);
111 if (!result.isModule()) {
112 return NoneType::object();
113 }
114 return *result;
115}
116
117RawObject FUNC(_imp, _create_dynamic)(Thread* thread, Arguments args) {
118 HandleScope scope(thread);
119 Runtime* runtime = thread->runtime();
120 Object name_obj(&scope, args.get(0));
121 if (!runtime->isInstanceOfStr(*name_obj)) {
122 return thread->raiseWithFmt(LayoutId::kTypeError,
123 "create_dynamic requires a str object");
124 }
125 Str name(&scope, strUnderlying(*name_obj));
126 Object path_obj(&scope, args.get(1));
127 if (!runtime->isInstanceOfStr(*path_obj)) {
128 return thread->raiseWithFmt(LayoutId::kTypeError,
129 "create_dynamic requires a str object");
130 }
131 Str path(&scope, strUnderlying(*path_obj));
132
133 return moduleLoadDynamicExtension(thread, name, path);
134}
135
136RawObject FUNC(_imp, acquire_lock)(Thread* thread, Arguments) {
137 importAcquireLock(thread);
138 return NoneType::object();
139}
140
141RawObject FUNC(_imp, create_builtin)(Thread* thread, Arguments args) {
142 HandleScope scope(thread);
143 Runtime* runtime = thread->runtime();
144 Object spec(&scope, args.get(0));
145 Object key(&scope, runtime->symbols()->at(ID(name)));
146 Object name_obj(&scope, getAttribute(thread, spec, key));
147 DCHECK(thread->isErrorValueOk(*name_obj), "error/exception mismatch");
148 if (name_obj.isError()) {
149 thread->clearPendingException();
150 return thread->raiseWithFmt(LayoutId::kTypeError,
151 "spec has no attribute 'name'");
152 }
153 if (!runtime->isInstanceOfStr(*name_obj)) {
154 return thread->raiseWithFmt(LayoutId::kTypeError,
155 "spec name must be an instance of str");
156 }
157 Str name(&scope, strUnderlying(*name_obj));
158 name = Runtime::internStr(thread, name);
159 Object result(&scope, ensureBuiltinModule(thread, name));
160 if (result.isErrorNotFound()) return NoneType::object();
161 return *result;
162}
163
164RawObject FUNC(_imp, exec_builtin)(Thread* thread, Arguments args) {
165 HandleScope scope(thread);
166 Runtime* runtime = thread->runtime();
167 Object module_obj(&scope, args.get(0));
168 if (!runtime->isInstanceOfModule(*module_obj)) {
169 return SmallInt::fromWord(0);
170 }
171 Module module(&scope, *module_obj);
172 Object module_def_obj(&scope, module.def());
173 if (!module_def_obj.isInt()) {
174 CHECK(!runtime->isInstanceOfInt(*module_def_obj),
175 "module_def must be an exact int as it's a C Ptr");
176 return SmallInt::fromWord(0);
177 }
178 Int module_def(&scope, *module_def_obj);
179 PyModuleDef* def = static_cast<PyModuleDef*>(module_def.asCPtr());
180 if (def == nullptr) {
181 return SmallInt::fromWord(0);
182 }
183 if (objectHasHandleCache(runtime, *module)) {
184 return SmallInt::fromWord(0);
185 }
186 return runtime->newInt(moduleExecDef(thread, module, def));
187}
188
189RawObject FUNC(_imp, get_frozen_object)(Thread* thread, Arguments args) {
190 HandleScope scope(thread);
191 Runtime* runtime = thread->runtime();
192 Object name_obj(&scope, args.get(0));
193 if (!runtime->isInstanceOfStr(*name_obj)) {
194 return thread->raiseWithFmt(LayoutId::kTypeError,
195 "get_frozen_object requires a str object");
196 }
197 Str name(&scope, strUnderlying(*name_obj));
198 const FrozenModule* frozen_module = frozenModuleByName(name);
199 if (frozen_module == nullptr) {
200 return thread->raiseWithFmt(LayoutId::kImportError,
201 "No such frozen object named '%S'", &name);
202 }
203 DCHECK(frozen_module->marshalled_code != nullptr,
204 "null code in frozen module");
205 word size = frozen_module->marshalled_code_length;
206 Marshal::Reader reader(&scope, thread,
207 View<byte>(frozen_module->marshalled_code, size));
208 // We don't write pyc headers for frozen modules because it would make
209 // bootstrapping tricky. Don't read the pyc header.
210 return reader.readObject();
211}
212
213RawObject FUNC(_imp, is_builtin)(Thread* thread, Arguments args) {
214 HandleScope scope(thread);
215 Runtime* runtime = thread->runtime();
216 Object name_obj(&scope, args.get(0));
217 if (!runtime->isInstanceOfStr(*name_obj)) {
218 return thread->raiseRequiresType(name_obj, ID(str));
219 }
220 Str name(&scope, strUnderlying(*name_obj));
221 name = Runtime::internStr(thread, name);
222 if (isFrozenPackage(name)) return SmallInt::fromWord(0);
223 bool result = isFrozenModule(name) || isBuiltinExtensionModule(name);
224 return SmallInt::fromWord(result ? 1 : 0);
225}
226
227RawObject FUNC(_imp, is_frozen)(Thread* thread, Arguments args) {
228 HandleScope scope(thread);
229 Object name_obj(&scope, args.get(0));
230 if (!thread->runtime()->isInstanceOfStr(*name_obj)) {
231 return thread->raiseWithFmt(LayoutId::kTypeError,
232 "is_frozen requires a str object");
233 }
234 Str name(&scope, strUnderlying(*name_obj));
235 name = Runtime::internStr(thread, name);
236 return Bool::fromBool(isFrozenModule(name));
237}
238
239RawObject FUNC(_imp, is_frozen_package)(Thread* thread, Arguments args) {
240 HandleScope scope(thread);
241 Object name_obj(&scope, args.get(0));
242 if (!thread->runtime()->isInstanceOfStr(*name_obj)) {
243 return thread->raiseWithFmt(LayoutId::kTypeError,
244 "is_frozen requires a str object");
245 }
246 Str name(&scope, strUnderlying(*name_obj));
247 name = Runtime::internStr(thread, name);
248 return Bool::fromBool(isFrozenPackage(name));
249}
250
251RawObject FUNC(_imp, lock_held)(Thread*, Arguments) {
252 return Bool::fromBool(import_lock_holder != nullptr);
253}
254
255RawObject FUNC(_imp, release_lock)(Thread* thread, Arguments) {
256 if (!importReleaseLock(thread)) {
257 return thread->raiseWithFmt(LayoutId::kRuntimeError,
258 "not holding the import lock");
259 }
260 return RawNoneType::object();
261}
262
263RawObject FUNC(_imp, source_hash)(Thread* thread, Arguments args) {
264 HandleScope scope(thread);
265 Runtime* runtime = thread->runtime();
266 Object key_obj(&scope, args.get(0));
267 if (!runtime->isInstanceOfInt(*key_obj)) {
268 return thread->raiseRequiresType(key_obj, ID(int));
269 }
270 Int key_int(&scope, intUnderlying(*key_obj));
271 if (key_int.numDigits() > 1) {
272 return thread->raiseWithFmt(LayoutId::kOverflowError,
273 "Python int too large to convert to C long");
274 }
275 word key = key_int.asWord();
276 Object source_obj(&scope, args.get(1));
277 if (!runtime->isByteslike(*source_obj)) {
278 return thread->raiseWithFmt(LayoutId::kTypeError,
279 "a bytes-like object is required, not '%T'",
280 &source_obj);
281 }
282 if (!runtime->isInstanceOfBytes(*source_obj)) {
283 // TODO(T38246066): support bytes-like objects other than bytes
284 UNIMPLEMENTED("bytes-like other than bytes");
285 }
286 Bytes source(&scope, bytesUnderlying(*source_obj));
287 uint64_t hash = Runtime::hashWithKey(source, key);
288 if (endian::native == endian::big) {
289 hash = __builtin_bswap64(hash);
290 }
291 return runtime->newBytesWithAll(
292 View<byte>(reinterpret_cast<byte*>(&hash), sizeof(hash)));
293}
294
295} // namespace py