this repo has no description
at trunk 295 lines 10 kB view raw
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