this repo has no description
at trunk 881 lines 31 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include "thread.h" 3 4#include <signal.h> 5 6#include <cerrno> 7#include <cstdarg> 8#include <cstdio> 9#include <cstring> 10 11#include "builtins-module.h" 12#include "exception-builtins.h" 13#include "file.h" 14#include "frame.h" 15#include "globals.h" 16#include "handles.h" 17#include "interpreter.h" 18#include "module-builtins.h" 19#include "objects.h" 20#include "profiling.h" 21#include "runtime.h" 22#include "tuple-builtins.h" 23#include "type-builtins.h" 24#include "visitor.h" 25 26namespace py { 27 28void Handles::visitPointers(PointerVisitor* visitor) { 29 for (Object* handle = head_; handle != nullptr; 30 handle = handle->nextHandle()) { 31 visitor->visitPointer(handle, PointerKind::kHandle); 32 } 33} 34 35RawObject uninitializedInterpreterFunc(Thread*) { 36 UNREACHABLE("interpreter main loop not initialized on this thread"); 37} 38 39thread_local Thread* Thread::current_thread_ = nullptr; 40 41Thread::Thread(Runtime* runtime, word size) : runtime_(runtime) { 42 CHECK(size % kPointerSize == 0, "size must be a multiple of kPointerSize"); 43 start_ = new byte[size](); // Zero-initialize the stack 44 // Stack growns down in order to match machine convention 45 end_ = start_ + size; 46 limit_ = start_; 47 stack_pointer_ = reinterpret_cast<RawObject*>(end_); 48 current_frame_ = pushInitialFrame(); 49 setCaughtExceptionState(runtime_->newExceptionState()); 50} 51 52Thread::~Thread() { delete[] start_; } 53 54void Thread::begin() { 55 Thread::setCurrentThread(this); 56 runtime_->interpreter()->setupThread(this); 57} 58 59void Thread::visitRoots(PointerVisitor* visitor) { 60 visitStackRoots(visitor); 61 handles()->visitPointers(visitor); 62 visitor->visitPointer(&api_repr_list_, PointerKind::kThread); 63 visitor->visitPointer(&asyncgen_hooks_finalizer_, PointerKind::kThread); 64 visitor->visitPointer(&asyncgen_hooks_first_iter_, PointerKind::kThread); 65 visitor->visitPointer(&caught_exc_stack_, PointerKind::kThread); 66 visitor->visitPointer(&contextvars_context_, PointerKind::kThread); 67 visitor->visitPointer(&pending_exc_traceback_, PointerKind::kThread); 68 visitor->visitPointer(&pending_exc_type_, PointerKind::kThread); 69 visitor->visitPointer(&pending_exc_value_, PointerKind::kThread); 70 visitor->visitPointer(&profiling_data_, PointerKind::kThread); 71 visitor->visitPointer(&str_offset_str_, PointerKind::kThread); 72} 73 74void Thread::visitStackRoots(PointerVisitor* visitor) { 75 auto address = reinterpret_cast<uword>(stackPointer()); 76 auto end = reinterpret_cast<uword>(end_); 77 std::memset(start_, 0, reinterpret_cast<byte*>(address) - start_); 78 for (; address < end; address += kPointerSize) { 79 visitor->visitPointer(reinterpret_cast<RawObject*>(address), 80 PointerKind::kStack); 81 } 82} 83 84Thread* Thread::current() { return Thread::current_thread_; } 85 86bool Thread::isMainThread() { return this == runtime_->mainThread(); } 87 88namespace { 89 90class UserVisibleFrameVisitor : public FrameVisitor { 91 public: 92 UserVisibleFrameVisitor(Thread* thread, word depth) 93 : thread_(thread), 94 scope_(thread), 95 result_(&scope_, NoneType::object()), 96 heap_frame_(&scope_, NoneType::object()), 97 next_heap_frame_(&scope_, NoneType::object()), 98 depth_(depth) {} 99 100 bool visit(Frame* frame) { 101 if (isHiddenFrame(frame)) { 102 return true; 103 } 104 if (call_ < depth_) { 105 call_++; 106 return true; 107 } 108 // Once visitor reaches the target depth, start creating a linked list of 109 // FrameProxys objects. 110 // TOOD(T63960421): Cache an already created object in the stack frame. 111 Function function(&scope_, frame->function()); 112 Object lasti(&scope_, NoneType::object()); 113 if (!frame->isNative()) { 114 lasti = SmallInt::fromWord(frame->virtualPC()); 115 } 116 heap_frame_ = thread_->runtime()->newFrameProxy(thread_, function, lasti); 117 // TODO(T89882231) unconditionally add frameLocals. We cannot currently do 118 // this because uninitialized variables are not cleared and will read 119 // arbitrary values. 120 if (function.hasOptimizedOrNewlocals()) { 121 FrameProxy::cast(*heap_frame_).setLocals(thread_->runtime()->newDict()); 122 } else { 123 FrameProxy::cast(*heap_frame_).setLocals(frameLocals(thread_, frame)); 124 } 125 if (result_.isNoneType()) { 126 // The head of the linked list is returned as the result. 127 result_ = *heap_frame_; 128 } else { 129 FrameProxy::cast(*next_heap_frame_).setBack(*heap_frame_); 130 } 131 next_heap_frame_ = *heap_frame_; 132 return true; 133 } 134 135 RawObject result() { return *result_; } 136 137 private: 138 bool isHiddenFrame(Frame* frame) { 139 if (frame == nullptr || frame->isSentinel()) { 140 return true; 141 } 142 RawFunction function = Function::cast(frame->function()); 143 word builtins_module_id = thread_->runtime()->builtinsModuleId(); 144 // PyCFunction do not generate a frame in cpython and therefore do 145 // not show up in sys._getframe(). Our builtin functions do create a 146 // frame so we hide frames of functions in builtins from the user. 147 // TODO(T64005113): This logic should be applied to each function. 148 if (function.moduleObject().isModule() && 149 Module::cast(function.moduleObject()).id() == builtins_module_id) { 150 return true; 151 } 152 return false; 153 } 154 155 Thread* thread_; 156 HandleScope scope_; 157 Object result_; 158 Object heap_frame_; 159 Object next_heap_frame_; 160 161 word call_ = 0; 162 word depth_; 163 164 DISALLOW_HEAP_ALLOCATION(); 165 DISALLOW_IMPLICIT_CONSTRUCTORS(UserVisibleFrameVisitor); 166}; 167 168} // namespace 169 170RawObject Thread::heapFrameAtDepth(word depth) { 171 UserVisibleFrameVisitor visitor(this, depth); 172 visitFrames(&visitor); 173 return visitor.result(); 174} 175 176void Thread::setCurrentThread(Thread* thread) { 177 Thread::current_thread_ = thread; 178} 179 180void Thread::clearInterrupt(InterruptKind kind) { 181 interrupt_flags_ &= ~kind; 182 if (interrupt_flags_ == 0) { 183 limit_ = start_; 184 } 185} 186 187void Thread::interrupt(InterruptKind kind) { 188 interrupt_flags_ |= kind; 189 limit_ = end_; 190} 191 192bool Thread::handleInterrupt(word size) { 193 // Is it a real stack overflow? 194 if (reinterpret_cast<byte*>(stackPointer()) - size < start_) { 195 raiseWithFmt(LayoutId::kRecursionError, "maximum recursion depth exceeded"); 196 return true; 197 } 198 uint8_t interrupt_flags = interrupt_flags_; 199 if ((interrupt_flags & kSignal) != 0 && 200 !runtime_->handlePendingSignals(this).isNoneType()) { 201 return true; 202 } 203 if (interrupt_flags & kReinitInterpreter) { 204 clearInterrupt(kReinitInterpreter); 205 runtime_->interpreter()->setupThread(this); 206 } 207 return false; 208} 209 210void Thread::handleInterruptWithFrame() { 211 if ((interrupt_flags_ & kProfile) != 0) { 212 profiling_call(this); 213 } 214} 215 216void Thread::linkFrame(Frame* frame) { 217 frame->setPreviousFrame(current_frame_); 218 current_frame_ = frame; 219} 220 221inline Frame* Thread::openAndLinkFrame(word size, word locals_offset) { 222 // Initialize the frame. 223 byte* new_sp = reinterpret_cast<byte*>(stack_pointer_) - size; 224 stack_pointer_ = reinterpret_cast<RawObject*>(new_sp); 225 Frame* frame = reinterpret_cast<Frame*>(new_sp); 226 frame->setLocalsOffset(locals_offset); 227 228 // return a pointer to the base of the frame 229 linkFrame(frame); 230 DCHECK(frame->isInvalid() == nullptr, "invalid frame"); 231 return frame; 232} 233 234ALWAYS_INLINE Frame* Thread::pushNativeFrameImpl(word locals_offset) { 235 return openAndLinkFrame(Frame::kSize, locals_offset); 236} 237 238NEVER_INLINE Frame* Thread::handleInterruptPushNativeFrame(word locals_offset) { 239 if (handleInterrupt(Frame::kSize)) { 240 return nullptr; 241 } 242 Frame* result = pushNativeFrameImpl(locals_offset); 243 handleInterruptWithFrame(); 244 return result; 245} 246 247Frame* Thread::pushNativeFrame(word nargs) { 248 word locals_offset = Frame::kSize + nargs * kPointerSize; 249 if (UNLIKELY(wouldStackOverflow(Frame::kSize))) { 250 return handleInterruptPushNativeFrame(locals_offset); 251 } 252 return pushNativeFrameImpl(locals_offset); 253} 254 255ALWAYS_INLINE Frame* Thread::pushCallFrameImpl(RawFunction function, 256 word stack_size, 257 word locals_offset) { 258 Frame* result = openAndLinkFrame(stack_size, locals_offset); 259 result->setBytecode(MutableBytes::cast(function.rewrittenBytecode())); 260 result->setCaches(function.caches()); 261 result->setVirtualPC(0); 262 result->setBlockStackDepthReturnMode(0); 263 return result; 264} 265 266NEVER_INLINE Frame* Thread::handleInterruptPushCallFrame( 267 RawFunction function, word max_stack_size, word initial_stack_size, 268 word locals_offset) { 269 if (handleInterrupt(max_stack_size)) { 270 return nullptr; 271 } 272 Frame* result = 273 pushCallFrameImpl(function, initial_stack_size, locals_offset); 274 handleInterruptWithFrame(); 275 return result; 276} 277 278Frame* Thread::pushCallFrame(RawFunction function) { 279 word initial_stack_size = Frame::kSize + function.totalVars() * kPointerSize; 280 word stack_size = SmallInt::cast(function.stacksizeOrBuiltin()).value(); 281 word max_stack_size = initial_stack_size + stack_size * kPointerSize; 282 word locals_offset = initial_stack_size + function.totalArgs() * kPointerSize; 283 if (UNLIKELY(wouldStackOverflow(max_stack_size))) { 284 return handleInterruptPushCallFrame(function, max_stack_size, 285 initial_stack_size, locals_offset); 286 } 287 return pushCallFrameImpl(function, initial_stack_size, locals_offset); 288} 289 290ALWAYS_INLINE Frame* Thread::pushGeneratorFrameImpl( 291 const GeneratorFrame& generator_frame, word size) { 292 word max_stack_size = generator_frame.maxStackSize(); 293 word stack_size = generator_frame.stackSize(); 294 word unused_stack = max_stack_size - stack_size; 295 size -= unused_stack * kPointerSize; 296 byte* src = reinterpret_cast<byte*>(generator_frame.address() + 297 RawGeneratorFrame::kFrameOffset + 298 unused_stack * kPointerSize); 299 byte* dest = reinterpret_cast<byte*>(stack_pointer_) - size; 300 std::memcpy(dest, src, size); 301 Frame* result = reinterpret_cast<Frame*>(dest + stack_size * kPointerSize); 302 setStackPointer(reinterpret_cast<RawObject*>(dest)); 303 linkFrame(result); 304 DCHECK(result->isInvalid() == nullptr, "invalid frame"); 305 return result; 306} 307 308NEVER_INLINE Frame* Thread::handleInterruptPushGeneratorFrame( 309 const GeneratorFrame& generator_frame, word size) { 310 if (handleInterrupt(size)) { 311 return nullptr; 312 } 313 Frame* result = pushGeneratorFrameImpl(generator_frame, size); 314 handleInterruptWithFrame(); 315 return result; 316} 317 318Frame* Thread::pushGeneratorFrame(const GeneratorFrame& generator_frame) { 319 word num_frame_words = generator_frame.numFrameWords(); 320 word size = num_frame_words * kPointerSize; 321 if (UNLIKELY(wouldStackOverflow(size))) { 322 return handleInterruptPushGeneratorFrame(generator_frame, size); 323 } 324 return pushGeneratorFrameImpl(generator_frame, size); 325} 326 327Frame* Thread::pushInitialFrame() { 328 byte* sp = end_ - Frame::kSize; 329 CHECK(sp > start_, "no space for initial frame"); 330 Frame* frame = reinterpret_cast<Frame*>(sp); 331 frame->setLocalsOffset(Frame::kSize); 332 stack_pointer_ = reinterpret_cast<RawObject*>(sp); 333 frame->setPreviousFrame(nullptr); 334 return frame; 335} 336 337Frame* Thread::popFrameToGeneratorFrame(const GeneratorFrame& generator_frame) { 338 word max_stack_size = generator_frame.maxStackSize(); 339 word stack_size = valueStackSize(); 340 word unused_stack = max_stack_size - stack_size; 341 DCHECK(stack_size <= max_stack_size, 342 "not enough space in RawGeneratorBase to save live stack"); 343 byte* dest = reinterpret_cast<byte*>(generator_frame.address() + 344 RawGeneratorFrame::kFrameOffset + 345 unused_stack * kPointerSize); 346 byte* src = reinterpret_cast<byte*>(valueStackBase() - stack_size); 347 word copy_size = 348 (generator_frame.numFrameWords() - unused_stack) * kPointerSize; 349 std::memcpy(dest, src, copy_size); 350 generator_frame.setStackSize(stack_size); 351 return popFrame(); 352} 353 354RawObject Thread::exec(const Code& code, const Module& module, 355 const Object& implicit_globals) { 356 HandleScope scope(this); 357 Object qualname(&scope, code.name()); 358 359 if (code.hasOptimizedOrNewlocals()) { 360 UNIMPLEMENTED("exec() on code with CO_OPTIMIZED / CO_NEWLOCALS"); 361 } 362 363 Runtime* runtime = this->runtime(); 364 Object builtins_module_obj(&scope, 365 moduleAtById(this, module, ID(__builtins__))); 366 if (builtins_module_obj.isErrorNotFound()) { 367 Module builtins(&scope, runtime->findModuleById(ID(builtins))); 368 DCHECK(!builtins.isErrorNotFound(), "invalid builtins module"); 369 Object proxy(&scope, builtins.moduleProxy()); 370 moduleAtPutById(this, module, ID(__builtins__), proxy); 371 } 372 Function function(&scope, 373 runtime->newFunctionWithCode(this, qualname, code, module)); 374 return callFunctionWithImplicitGlobals(function, implicit_globals); 375} 376 377RawObject Thread::callFunctionWithImplicitGlobals( 378 const Function& function, const Object& implicit_globals) { 379 CHECK(!function.hasOptimizedOrNewlocals(), 380 "function must not have CO_OPTIMIZED or CO_NEWLOCALS"); 381 382 // Push implicit globals and function. 383 stackPush(*implicit_globals); 384 stackPush(*function); 385 Frame* frame = pushCallFrame(*function); 386 if (frame == nullptr) { 387 return Error::exception(); 388 } 389 if (function.hasFreevarsOrCellvars()) { 390 processFreevarsAndCellvars(this, frame); 391 } 392 RawObject result = Interpreter::execute(this); 393 DCHECK(stackTop() == *implicit_globals, "stack mismatch"); 394 stackDrop(1); 395 return result; 396} 397 398RawObject Thread::invokeMethod1(const Object& receiver, SymbolId selector) { 399 HandleScope scope(this); 400 Object method(&scope, Interpreter::lookupMethod(this, receiver, selector)); 401 if (method.isError()) return *method; 402 return Interpreter::callMethod1(this, method, receiver); 403} 404 405RawObject Thread::invokeMethod2(const Object& receiver, SymbolId selector, 406 const Object& arg1) { 407 HandleScope scope(this); 408 Object method(&scope, Interpreter::lookupMethod(this, receiver, selector)); 409 if (method.isError()) return *method; 410 return Interpreter::callMethod2(this, method, receiver, arg1); 411} 412 413RawObject Thread::invokeMethod3(const Object& receiver, SymbolId selector, 414 const Object& arg1, const Object& arg2) { 415 HandleScope scope(this); 416 Object method(&scope, Interpreter::lookupMethod(this, receiver, selector)); 417 if (method.isError()) return *method; 418 return Interpreter::callMethod3(this, method, receiver, arg1, arg2); 419} 420 421RawObject Thread::invokeMethodStatic1(LayoutId type, SymbolId method_name, 422 const Object& receiver) { 423 HandleScope scope(this); 424 Object type_obj(&scope, runtime()->typeAt(type)); 425 if (type_obj.isError()) return *type_obj; 426 Type type_handle(&scope, *type_obj); 427 Object method(&scope, typeLookupInMroById(this, *type_handle, method_name)); 428 if (method.isError()) return *method; 429 return Interpreter::callMethod1(this, method, receiver); 430} 431 432RawObject Thread::invokeMethodStatic2(LayoutId type, SymbolId method_name, 433 const Object& receiver, 434 const Object& arg1) { 435 HandleScope scope(this); 436 Object type_obj(&scope, runtime()->typeAt(type)); 437 if (type_obj.isError()) return *type_obj; 438 Type type_handle(&scope, *type_obj); 439 Object method(&scope, typeLookupInMroById(this, *type_handle, method_name)); 440 if (method.isError()) return *method; 441 return Interpreter::callMethod2(this, method, receiver, arg1); 442} 443 444RawObject Thread::invokeMethodStatic3(LayoutId type, SymbolId method_name, 445 const Object& receiver, 446 const Object& arg1, const Object& arg2) { 447 HandleScope scope(this); 448 Object type_obj(&scope, runtime()->typeAt(type)); 449 if (type_obj.isError()) return *type_obj; 450 Type type_handle(&scope, *type_obj); 451 Object method(&scope, typeLookupInMroById(this, *type_handle, method_name)); 452 if (method.isError()) return *method; 453 return Interpreter::callMethod3(this, method, receiver, arg1, arg2); 454} 455 456RawObject Thread::invokeMethodStatic4(LayoutId type, SymbolId method_name, 457 const Object& receiver, 458 const Object& arg1, const Object& arg2, 459 const Object& arg3) { 460 HandleScope scope(this); 461 Object type_obj(&scope, runtime()->typeAt(type)); 462 if (type_obj.isError()) return *type_obj; 463 Type type_handle(&scope, *type_obj); 464 Object method(&scope, typeLookupInMroById(this, *type_handle, method_name)); 465 if (method.isError()) return *method; 466 return Interpreter::callMethod4(this, method, receiver, arg1, arg2, arg3); 467} 468 469RawObject Thread::invokeFunction0(SymbolId module, SymbolId name) { 470 HandleScope scope(this); 471 Object func(&scope, runtime()->lookupNameInModule(this, module, name)); 472 if (func.isError()) return *func; 473 return Interpreter::call0(this, func); 474} 475 476RawObject Thread::invokeFunction1(SymbolId module, SymbolId name, 477 const Object& arg1) { 478 HandleScope scope(this); 479 Object func(&scope, runtime()->lookupNameInModule(this, module, name)); 480 if (func.isError()) return *func; 481 return Interpreter::call1(this, func, arg1); 482} 483 484RawObject Thread::invokeFunction2(SymbolId module, SymbolId name, 485 const Object& arg1, const Object& arg2) { 486 HandleScope scope(this); 487 Object func(&scope, runtime()->lookupNameInModule(this, module, name)); 488 if (func.isError()) return *func; 489 return Interpreter::call2(this, func, arg1, arg2); 490} 491 492RawObject Thread::invokeFunction3(SymbolId module, SymbolId name, 493 const Object& arg1, const Object& arg2, 494 const Object& arg3) { 495 HandleScope scope(this); 496 Object func(&scope, runtime()->lookupNameInModule(this, module, name)); 497 if (func.isError()) return *func; 498 return Interpreter::call3(this, func, arg1, arg2, arg3); 499} 500 501RawObject Thread::invokeFunction4(SymbolId module, SymbolId name, 502 const Object& arg1, const Object& arg2, 503 const Object& arg3, const Object& arg4) { 504 HandleScope scope(this); 505 Object func(&scope, runtime()->lookupNameInModule(this, module, name)); 506 if (func.isError()) return *func; 507 return Interpreter::call4(this, func, arg1, arg2, arg3, arg4); 508} 509 510RawObject Thread::invokeFunction5(SymbolId module, SymbolId name, 511 const Object& arg1, const Object& arg2, 512 const Object& arg3, const Object& arg4, 513 const Object& arg5) { 514 HandleScope scope(this); 515 Object func(&scope, runtime()->lookupNameInModule(this, module, name)); 516 if (func.isError()) return *func; 517 return Interpreter::call5(this, func, arg1, arg2, arg3, arg4, arg5); 518} 519 520RawObject Thread::invokeFunction6(SymbolId module, SymbolId name, 521 const Object& arg1, const Object& arg2, 522 const Object& arg3, const Object& arg4, 523 const Object& arg5, const Object& arg6) { 524 HandleScope scope(this); 525 Object func(&scope, runtime()->lookupNameInModule(this, module, name)); 526 if (func.isError()) return *func; 527 return Interpreter::call6(this, func, arg1, arg2, arg3, arg4, arg5, arg6); 528} 529 530RawObject Thread::raise(LayoutId type, RawObject value) { 531 return raiseWithType(runtime()->typeAt(type), value); 532} 533 534RawObject Thread::raiseWithType(RawObject type, RawObject value) { 535 DCHECK(!hasPendingException(), "unhandled exception lingering"); 536 HandleScope scope(this); 537 Type type_obj(&scope, type); 538 Object value_obj(&scope, value); 539 Object traceback_obj(&scope, NoneType::object()); 540 // If raise is called with an exception instance use the original traceback 541 if (runtime()->isInstanceOfBaseException(*value_obj)) { 542 traceback_obj = value_obj.rawCast<RawBaseException>().traceback(); 543 } 544 545 value_obj = chainExceptionContext(type_obj, value_obj); 546 if (value_obj.isErrorException()) return Error::exception(); 547 548 setPendingExceptionType(*type_obj); 549 setPendingExceptionValue(*value_obj); 550 setPendingExceptionTraceback(*traceback_obj); 551 return Error::exception(); 552} 553 554RawObject Thread::chainExceptionContext(const Type& type, const Object& value) { 555 HandleScope scope(this); 556 Object caught_exc_state_obj(&scope, topmostCaughtExceptionState()); 557 if (caught_exc_state_obj.isNoneType()) { 558 return *value; 559 } 560 ExceptionState caught_exc_state(&scope, *caught_exc_state_obj); 561 562 Object fixed_value(&scope, *value); 563 if (!runtime()->isInstanceOfBaseException(*value)) { 564 // Perform partial normalization before attempting to set __context__. 565 fixed_value = createException(this, type, value); 566 if (fixed_value.isError()) return *fixed_value; 567 } 568 569 // Avoid creating cycles by breaking any link from caught_value to value 570 // before setting value's __context__. 571 BaseException caught_value(&scope, caught_exc_state.value()); 572 if (*fixed_value == *caught_value) return *fixed_value; 573 BaseException exc(&scope, *caught_value); 574 Object context(&scope, NoneType::object()); 575 while (!(context = exc.context()).isNoneType()) { 576 if (*context == *fixed_value) { 577 exc.setContext(Unbound::object()); 578 break; 579 } 580 exc = *context; 581 } 582 583 BaseException(&scope, *fixed_value).setContext(*caught_value); 584 return *fixed_value; 585} 586 587RawObject Thread::raiseWithFmt(LayoutId type, const char* fmt, ...) { 588 va_list args; 589 va_start(args, fmt); 590 HandleScope scope(this); 591 Object message(&scope, runtime()->newStrFromFmtV(this, fmt, args)); 592 va_end(args); 593 return raise(type, *message); 594} 595 596RawObject Thread::raiseWithFmtChainingPendingAsCause(LayoutId type, 597 const char* fmt, ...) { 598 HandleScope scope(this); 599 600 va_list args; 601 va_start(args, fmt); 602 Object message(&scope, runtime()->newStrFromFmtV(this, fmt, args)); 603 va_end(args); 604 605 Object pending_type(&scope, pendingExceptionType()); 606 Object pending_value(&scope, pendingExceptionValue()); 607 Object pending_traceback(&scope, pendingExceptionTraceback()); 608 clearPendingException(); 609 normalizeException(this, &pending_type, &pending_value, &pending_traceback); 610 611 Type new_exc_type(&scope, runtime()->typeAt(type)); 612 BaseException new_exc(&scope, createException(this, new_exc_type, message)); 613 new_exc.setCause(*pending_value); 614 new_exc.setContext(*pending_value); 615 setPendingExceptionType(*new_exc_type); 616 setPendingExceptionValue(*new_exc); 617 setPendingExceptionTraceback(NoneType::object()); 618 return Error::exception(); 619} 620 621// Convenience method for throwing a binary-operation-specific TypeError 622// exception with an error message. 623RawObject Thread::raiseUnsupportedBinaryOperation( 624 const Handle<RawObject>& left, const Handle<RawObject>& right, 625 SymbolId op_name) { 626 return raiseWithFmt(LayoutId::kTypeError, "%T.%Y(%T) is not supported", &left, 627 op_name, &right); 628} 629 630void Thread::raiseBadArgument() { 631 raiseWithFmt(LayoutId::kTypeError, 632 "bad argument type for built-in operation"); 633} 634 635RawObject Thread::raiseBadInternalCall() { 636 return raiseWithFmt(LayoutId::kSystemError, 637 "bad argument to internal function"); 638} 639 640RawObject Thread::raiseMemoryError() { 641 return raise(LayoutId::kMemoryError, NoneType::object()); 642} 643 644RawObject Thread::raiseOSErrorFromErrno(int errno_value) { 645 HandleScope scope(this); 646 Object type(&scope, runtime()->typeAt(LayoutId::kOSError)); 647 NoneType none(&scope, NoneType::object()); 648 return raiseFromErrnoWithFilenames(type, errno_value, none, none); 649} 650 651RawObject Thread::raiseFromErrnoWithFilenames(const Object& type, 652 int errno_value, 653 const Object& filename0, 654 const Object& filename1) { 655 HandleScope scope(this); 656 if (errno_value == EINTR) { 657 Object result(&scope, runtime_->handlePendingSignals(this)); 658 if (result.isErrorException()) return *result; 659 } 660 661 stackPush(*type); 662 stackPush(SmallInt::fromWord(errno_value)); 663 stackPush(errno_value == 0 664 ? runtime_->symbols()->at(ID(Error)) 665 : Runtime::internStrFromCStr(this, std::strerror(errno_value))); 666 word nargs = 2; 667 if (!filename0.isNoneType()) { 668 stackPush(*filename0); 669 ++nargs; 670 if (!filename1.isNoneType()) { 671 stackPush(SmallInt::fromWord(0)); 672 stackPush(*filename1); 673 nargs += 2; 674 } 675 } else { 676 DCHECK(filename1.isNoneType(), "expected filename1 to be None"); 677 } 678 Object exception(&scope, Interpreter::call(this, nargs)); 679 if (exception.isErrorException()) return *exception; 680 return raiseWithType(runtime_->typeOf(*exception), *exception); 681} 682 683RawObject Thread::raiseRequiresType(const Object& obj, SymbolId expected_type) { 684 HandleScope scope(this); 685 Function function(&scope, currentFrame()->function()); 686 Str function_name(&scope, function.name()); 687 return raiseWithFmt(LayoutId::kTypeError, 688 "'%S' for '%Y' objects doesn't apply to a '%T' object", 689 &function_name, expected_type, &obj); 690} 691 692RawObject Thread::raiseStopAsyncIteration() { 693 return raise(LayoutId::kStopAsyncIteration, NoneType::object()); 694} 695 696RawObject Thread::raiseStopIteration() { 697 return raise(LayoutId::kStopIteration, NoneType::object()); 698} 699 700RawObject Thread::raiseStopIterationWithValue(const Object& value) { 701 if (runtime()->isInstanceOfTuple(*value) || 702 runtime()->isInstanceOfBaseException(*value)) { 703 // TODO(T67598788): Remove this special case. For now this works around 704 // the behavior of normalizeException() when it's called in 705 // Interpreter::unwind() as part of returning values from generators. Our 706 // desired end-state is StopIterations will be treated as a special 707 // optimized path which, among other properties, are not processed by 708 // normalization. 709 HandleScope scope(this); 710 Layout layout(&scope, runtime()->layoutAt(LayoutId::kStopIteration)); 711 StopIteration stop_iteration(&scope, runtime()->newInstance(layout)); 712 stop_iteration.setArgs(runtime()->newTupleWith1(value)); 713 stop_iteration.setValue(*value); 714 stop_iteration.setCause(Unbound::object()); 715 stop_iteration.setContext(Unbound::object()); 716 stop_iteration.setTraceback(Unbound::object()); 717 stop_iteration.setSuppressContext(RawBool::falseObj()); 718 return raise(LayoutId::kStopIteration, *stop_iteration); 719 } 720 return raise(LayoutId::kStopIteration, *value); 721} 722 723bool Thread::hasPendingException() { return !pending_exc_type_.isNoneType(); } 724 725bool Thread::hasPendingStopIteration() { 726 if (pending_exc_type_.isType()) { 727 return Type::cast(pending_exc_type_).builtinBase() == 728 LayoutId::kStopIteration; 729 } 730 if (runtime()->isInstanceOfType(pending_exc_type_)) { 731 HandleScope scope(this); 732 Type type(&scope, pending_exc_type_); 733 return type.builtinBase() == LayoutId::kStopIteration; 734 } 735 return false; 736} 737 738bool Thread::clearPendingStopIteration() { 739 if (hasPendingStopIteration()) { 740 clearPendingException(); 741 return true; 742 } 743 return false; 744} 745 746RawObject Thread::pendingStopIterationValue() { 747 DCHECK(hasPendingStopIteration(), 748 "Shouldn't be called without a pending StopIteration"); 749 750 HandleScope scope(this); 751 Object exc_value(&scope, pendingExceptionValue()); 752 if (runtime()->isInstanceOfStopIteration(*exc_value)) { 753 StopIteration si(&scope, *exc_value); 754 return si.value(); 755 } 756 if (runtime()->isInstanceOfTuple(*exc_value)) { 757 return tupleUnderlying(*exc_value).at(0); 758 } 759 return *exc_value; 760} 761 762void Thread::ignorePendingException() { 763 if (!hasPendingException()) { 764 return; 765 } 766 fprintf(stderr, "ignore pending exception"); 767 if (pendingExceptionValue().isStr()) { 768 RawStr message = Str::cast(pendingExceptionValue()); 769 word len = message.length(); 770 byte* buffer = new byte[len + 1]; 771 message.copyTo(buffer, len); 772 buffer[len] = 0; 773 fprintf(stderr, ": %s", buffer); 774 delete[] buffer; 775 } 776 fprintf(stderr, "\n"); 777 clearPendingException(); 778 runtime_->printTraceback(this, File::kStderr); 779} 780 781void Thread::clearPendingException() { 782 setPendingExceptionType(NoneType::object()); 783 setPendingExceptionValue(NoneType::object()); 784 setPendingExceptionTraceback(NoneType::object()); 785} 786 787bool Thread::pendingExceptionMatches(LayoutId type) { 788 return typeIsSubclass(pendingExceptionType(), runtime()->typeAt(type)); 789} 790 791void Thread::setCaughtExceptionType(RawObject type) { 792 ExceptionState::cast(caught_exc_stack_).setType(type); 793} 794 795void Thread::setCaughtExceptionValue(RawObject value) { 796 ExceptionState::cast(caught_exc_stack_).setValue(value); 797} 798 799void Thread::setCaughtExceptionTraceback(RawObject traceback) { 800 ExceptionState::cast(caught_exc_stack_).setTraceback(traceback); 801} 802 803RawObject Thread::caughtExceptionState() { return caught_exc_stack_; } 804 805void Thread::setCaughtExceptionState(RawObject state) { 806 caught_exc_stack_ = state; 807} 808 809RawObject Thread::topmostCaughtExceptionState() { 810 HandleScope scope(this); 811 Object exc_state(&scope, caught_exc_stack_); 812 while (!exc_state.isNoneType() && 813 ExceptionState::cast(*exc_state).type().isNoneType()) { 814 exc_state = ExceptionState::cast(*exc_state).previous(); 815 } 816 return *exc_state; 817} 818 819bool Thread::isErrorValueOk(RawObject obj) { 820 return (!obj.isError() && !hasPendingException()) || 821 (obj.isErrorException() && hasPendingException()); 822} 823 824void Thread::visitFrames(FrameVisitor* visitor) { 825 Frame* frame = currentFrame(); 826 while (!frame->isSentinel()) { 827 if (!visitor->visit(frame)) { 828 break; 829 } 830 frame = frame->previousFrame(); 831 } 832} 833 834void Thread::enableProfiling() { interrupt(kProfile); } 835 836void Thread::disableProfiling() { clearInterrupt(kProfile); } 837 838RawObject Thread::reprEnter(const Object& obj) { 839 HandleScope scope(this); 840 if (api_repr_list_.isNoneType()) { 841 api_repr_list_ = runtime_->newList(); 842 } 843 List list(&scope, api_repr_list_); 844 for (word i = list.numItems() - 1; i >= 0; i--) { 845 if (list.at(i) == *obj) { 846 return RawBool::trueObj(); 847 } 848 } 849 // TODO(emacs): When there is better error handling, raise an exception. 850 runtime_->listAdd(this, list, obj); 851 return RawBool::falseObj(); 852} 853 854void Thread::reprLeave(const Object& obj) { 855 HandleScope scope(this); 856 List list(&scope, api_repr_list_); 857 for (word i = list.numItems() - 1; i >= 0; i--) { 858 if (list.at(i) == *obj) { 859 list.atPut(i, Unbound::object()); 860 break; 861 } 862 } 863} 864 865word Thread::strOffset(const Str& str, word index) { 866 if (str != str_offset_str_) { 867 str_offset_str_ = *str; 868 str_offset_index_ = index; 869 str_offset_offset_ = str.offsetByCodePoints(0, index); 870 return str_offset_offset_; 871 } 872 word index_diff = index - str_offset_index_; 873 word offset = str.offsetByCodePoints(str_offset_offset_, index_diff); 874 if (0 <= offset && offset < str.length()) { 875 str_offset_index_ = index; 876 str_offset_offset_ = offset; 877 } 878 return offset; 879} 880 881} // namespace py