this repo has no description
at trunk 666 lines 33 kB view raw
1/* Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) */ 2#pragma once 3 4#include "bytecode.h" 5#include "frame.h" 6#include "globals.h" 7#include "handles.h" 8#include "symbols.h" 9#include "trampolines.h" 10 11namespace py { 12 13class RawObject; 14class Frame; 15class Thread; 16 17// Bitset indicating how a cached binary operation needs to be called. 18enum BinaryOpFlags : uint8_t { 19 kBinaryOpNone = 0, 20 // Swap arguments when calling the method. 21 kBinaryOpReflected = 1 << 0, 22 // Retry alternative method when method returns `NotImplemented`. Should try 23 // the non-reflected op if the `kBinaryOpReflected` flag is set and vice 24 // versa. 25 kBinaryOpNotImplementedRetry = 1 << 1, 26 // This flag is set when the cached method is an in-place operation (such as 27 // __iadd__). 28 kInplaceBinaryOpRetry = 1 << 2, 29}; 30 31// Different caching strategies for the resolved location of a LOAD_ATTR 32enum class LoadAttrKind { 33 kInstanceOffset = 1, 34 kInstanceFunction, 35 kInstanceProperty, 36 kInstanceSlotDescr, 37 kInstanceType, 38 kInstanceTypeDescr, 39 kModule, 40 kType, 41 kDunderClass, 42 kUnknown, 43}; 44 45enum class ICState { 46 kAnamorphic, 47 kMonomorphic, 48 kPolymorphic, 49}; 50 51class Interpreter { 52 public: 53 enum class BinaryOp { 54 ADD, 55 SUB, 56 MUL, 57 MATMUL, 58 TRUEDIV, 59 FLOORDIV, 60 MOD, 61 DIVMOD, 62 POW, 63 LSHIFT, 64 RSHIFT, 65 AND, 66 XOR, 67 OR 68 }; 69 70 enum class UnaryOp { 71 NEGATIVE, 72 POSITIVE, 73 NOT, 74 INVERT, 75 }; 76 77 enum class Continue { 78 NEXT, 79 UNWIND, 80 RETURN, 81 YIELD, 82 DEOPT, 83 }; 84 static const word kNumContinues = 5; 85 86 using OpcodeHandler = Continue (*)(Thread* thread, word arg); 87 88 virtual ~Interpreter(); 89 // Initialize per-thread interpreter state. Must be called on each thread 90 // before the interpreter can execute code on it. 91 virtual void setupThread(Thread* thread) = 0; 92 93 virtual void* entryAsm(const Function& function) = 0; 94 95 virtual void setOpcodeCounting(bool enabled) = 0; 96 97 static RawObject execute(Thread* thread); 98 static RawObject resumeGenerator(Thread* thread, 99 const GeneratorBase& generator, 100 const Object& send_value); 101 static RawObject resumeGeneratorWithRaise(Thread* thread, 102 const GeneratorBase& generator, 103 const Object& type, 104 const Object& value, 105 const Object& traceback); 106 107 static RawObject call(Thread* thread, word nargs); 108 static RawObject callEx(Thread* thread, word flags); 109 static RawObject callKw(Thread* thread, word nargs); 110 111 // Perform positional call of function `function`. Does not work for arbitrary 112 // callables objects; that case requires `call`. 113 static RawObject callFunction(Thread* thread, word nargs, RawObject function); 114 115 // Calls __hash__ on `value`, checks result and postprocesses. Returns a 116 // SmallInt or Error::exception(). 117 static RawObject hash(Thread* thread, const Object& value); 118 119 // batch concat/join <num> string objects on the stack (no conversion) 120 static RawObject stringJoin(Thread* thread, RawObject* sp, word num); 121 122 static RawObject isTrue(Thread* thread, RawObject value_obj); 123 124 static RawObject callDescriptorGet(Thread* thread, const Object& descriptor, 125 const Object& receiver, 126 const Object& receiver_type); 127 128 static RawObject callDescriptorSet(Thread* thread, const Object& descriptor, 129 const Object& receiver, 130 const Object& value); 131 132 static RawObject callDescriptorDelete(Thread* thread, 133 const Object& descriptor, 134 const Object& receiver); 135 136 // Lookup method in type of `receiver`. Only performs a lookup in the type, 137 // not in `receiver` itself. As a shortcut this function does not create 138 // `BoundMethod` objects hence the result must only be used with `callMethodX` 139 // or `tailcallMethodX`. 140 static RawObject lookupMethod(Thread* thread, const Object& receiver, 141 SymbolId selector); 142 143 // Call callable object without parameters. 144 static RawObject call0(Thread* thread, const Object& callable); 145 // Call callable object with 1 parameter. 146 static RawObject call1(Thread* thread, const Object& callable, 147 const Object& arg1); 148 // Call callable object with 2 parameters. 149 static RawObject call2(Thread* thread, const Object& callable, 150 const Object& arg1, const Object& arg2); 151 // Call callable object with 3 parameters. 152 static RawObject call3(Thread* thread, const Object& callable, 153 const Object& arg1, const Object& arg2, 154 const Object& arg3); 155 // Call callable object with 4 parameters. 156 static RawObject call4(Thread* thread, const Object& callable, 157 const Object& arg1, const Object& arg2, 158 const Object& arg3, const Object& arg4); 159 // Call callable object with 5 parameters. 160 static RawObject call5(Thread* thread, const Object& callable, 161 const Object& arg1, const Object& arg2, 162 const Object& arg3, const Object& arg4, 163 const Object& arg5); 164 // Call callable object with 6 parameters. 165 static RawObject call6(Thread* thread, const Object& callable, 166 const Object& arg1, const Object& arg2, 167 const Object& arg3, const Object& arg4, 168 const Object& arg5, const Object& arg6); 169 170 // Call method with 1 argument; must only be used with objects looked up via 171 // `lookupMethod`. 172 static RawObject callMethod1(Thread* thread, const Object& method, 173 const Object& self); 174 175 // Call method with 2 arguments; must only be used with objects looked up via 176 // `lookupMethod`. 177 static RawObject callMethod2(Thread* thread, const Object& method, 178 const Object& self, const Object& other); 179 180 // Call method with 3 arguments; must only be used with objects looked up via 181 // `lookupMethod`. 182 static RawObject callMethod3(Thread* thread, const Object& method, 183 const Object& self, const Object& arg1, 184 const Object& arg2); 185 186 // Call method with 4 arguments; must only be used with objects looked up via 187 // `lookupMethod`. 188 static RawObject callMethod4(Thread* thread, const Object& method, 189 const Object& self, const Object& arg1, 190 const Object& arg2, const Object& arg3); 191 192 struct PrepareCallableResult { 193 RawObject function; 194 word nargs; 195 }; 196 197 // Prepare the stack to for a positional or keyword call by normalizing the 198 // callable object using prepareCallableObject(). 199 // 200 // Returns the concrete Function that should be called. Updates nargs if a 201 // self object was unpacked from the callable and inserted into the stack. 202 // 203 // Not intended for public use; only here for testing purposes. 204 static PrepareCallableResult prepareCallableCall(Thread* thread, word nargs, 205 word callable_idx); 206 207 static RawObject unaryOperation(Thread* thread, const Object& self, 208 SymbolId selector); 209 210 static RawObject binaryOperation(Thread* thread, BinaryOp op, 211 const Object& left, const Object& right); 212 static Continue binaryOpUpdateCache(Thread* thread, word arg, word cache); 213 214 // Lookup and invoke a binary operation (like `__add__`, `__sub__`, ...). 215 // Sets `method_out` and `flags_out` to the lookup result if it is possible 216 // to cache it. 217 static RawObject binaryOperationSetMethod(Thread* thread, BinaryOp op, 218 const Object& left, 219 const Object& right, 220 Object* method_out, 221 BinaryOpFlags* flags_out); 222 223 // Calls a previously cached binary operation. Note that the caller still 224 // needs to check for a `NotImplemented` result and call 225 // `binaryOperationRetry()` if necessary. 226 static RawObject binaryOperationWithMethod(Thread* thread, RawObject method, 227 BinaryOpFlags flags, 228 RawObject left, RawObject right); 229 230 // Calls the normal binary operation if `flags` has the `kBinaryOpReflected` 231 // and the `kBinaryOpNotImplementedRetry` bits are set; calls the reflected 232 // operation if just `kBinaryOpNotImplementedRetry` is set. Raises an error 233 // if any of the two operations raised `NotImplemented` or none was called. 234 // 235 // This represents the second half of the binary operation calling mechanism 236 // after we attempted a first lookup and call. It is a separate function so we 237 // can use it independently of the first lookup using inline caching. 238 static RawObject binaryOperationRetry(Thread* thread, BinaryOp op, 239 BinaryOpFlags flags, const Object& left, 240 const Object& right); 241 242 // Slow path for the BINARY_SUBSCR opcode that updates the cache at the given 243 // index when appropriate. May also be used as a non-caching slow path by 244 // passing a negative index. 245 static Continue binarySubscrUpdateCache(Thread* thread, word cache); 246 247 // Slow path for the STORE_SUBSCR opcode that updates the cache at the given 248 // index when appropriate. May also be used as a non-caching slow path by 249 // passing a negative index. 250 static Continue storeSubscrUpdateCache(Thread* thread, word cache); 251 252 static Continue compareInUpdateCache(Thread* thread, word cache); 253 254 static RawObject inplaceOperation(Thread* thread, BinaryOp op, 255 const Object& left, const Object& right); 256 static Continue inplaceOpUpdateCache(Thread* thread, word arg, word cache); 257 258 static RawObject inplaceOperationSetMethod(Thread* thread, BinaryOp op, 259 const Object& left, 260 const Object& right, 261 Object* method_out, 262 BinaryOpFlags* flags_out); 263 264 static RawObject compareOperationRetry(Thread* thread, CompareOp op, 265 BinaryOpFlags flags, 266 const Object& left, 267 const Object& right); 268 269 static RawObject compareOperationSetMethod(Thread* thread, CompareOp op, 270 const Object& left, 271 const Object& right, 272 Object* method_out, 273 BinaryOpFlags* flags_out); 274 275 static RawObject compareOperation(Thread* thread, CompareOp op, 276 const Object& left, const Object& right); 277 static Continue compareOpUpdateCache(Thread* thread, word arg, word cache); 278 279 static RawObject createIterator(Thread* thread, const Object& iterable); 280 281 static RawObject sequenceIterSearch(Thread* thread, const Object& value, 282 const Object& container); 283 284 static RawObject sequenceContains(Thread* thread, const Object& value, 285 const Object& container); 286 287 static RawObject sequenceContainsSetMethod(Thread* thread, 288 const Object& value, 289 const Object& container, 290 Object* method_out); 291 292 static RawObject unpackSequence(Thread* thread, word length, 293 RawObject iterable); 294 295 static RawObject loadAttrWithLocation(Thread* thread, RawObject receiver, 296 RawObject location); 297 298 static RawObject importAllFrom(Thread* thread, Frame* frame, 299 const Object& object); 300 301 // Process the operands to the RAISE_VARARGS bytecode into a pending exception 302 // on ctx->thread. 303 static void raise(Thread* thread, RawObject exc_obj, RawObject cause_obj); 304 305 static RawObject storeAttrSetLocation(Thread* thread, const Object& object, 306 const Object& name, const Object& value, 307 Object* location_out); 308 static void storeAttrWithLocation(Thread* thread, RawObject receiver, 309 RawObject location, RawObject value); 310 311 static SymbolId binaryOperationSelector(BinaryOp op); 312 static SymbolId swappedBinaryOperationSelector(BinaryOp op); 313 314 static SymbolId inplaceOperationSelector(BinaryOp op); 315 316 static SymbolId comparisonSelector(CompareOp op); 317 static SymbolId swappedComparisonSelector(CompareOp op); 318 319 // Unwind the stack for a pending exception. A return value that is not 320 // `Error::error()` indicates that we should exit the interpreter loop and 321 // return that value. 322 static RawObject unwind(Thread* thread); 323 324 // Unwind an ExceptHandler from the stack, restoring the previous handler 325 // state. 326 static void unwindExceptHandler(Thread* thread, TryBlock block); 327 328 // Pop from the block stack until a handler that cares about 'return' is 329 // found, or the stack is emptied. A return value that is not `Error::error()` 330 // indicates that we should exit the interpreter loop and return that value. 331 static RawObject handleReturn(Thread* thread); 332 333 // Opcode handlers 334 // 335 // Handlers that never exit the Frame return void, while those that could 336 // return bool. 337 // 338 // A return value of true means the top Frame owned by this Interpreter is 339 // finished. The dispatch loop will pop TOS, pop the Frame, and return the 340 // popped value. For raised exceptions, this value will always be Error, and 341 // for opcodes like RETURN_VALUE it will be the returned value. 342 // 343 // A return value of false means execution should continue as normal in the 344 // current Frame. 345 static Continue doBeforeAsyncWith(Thread* thread, word arg); 346 static Continue doBeginFinally(Thread* thread, word arg); 347 static Continue doBinaryAdd(Thread* thread, word arg); 348 static Continue doBinaryAnd(Thread* thread, word arg); 349 static Continue doBinaryFloorDivide(Thread* thread, word arg); 350 static Continue doBinaryLshift(Thread* thread, word arg); 351 static Continue doBinaryMatrixMultiply(Thread* thread, word arg); 352 static Continue doBinaryModulo(Thread* thread, word arg); 353 static Continue doBinaryMultiply(Thread* thread, word arg); 354 static Continue doBinaryOpMonomorphic(Thread* thread, word arg); 355 static Continue doBinaryOpPolymorphic(Thread* thread, word arg); 356 static Continue doBinaryAddSmallInt(Thread* thread, word arg); 357 static Continue doBinaryAndSmallInt(Thread* thread, word arg); 358 static Continue doBinaryMulSmallInt(Thread* thread, word arg); 359 static Continue doBinaryFloordivSmallInt(Thread* thread, word arg); 360 static Continue doBinarySubSmallInt(Thread* thread, word arg); 361 static Continue doBinaryOrSmallInt(Thread* thread, word arg); 362 static Continue doBinaryOpAnamorphic(Thread* thread, word arg); 363 static Continue doBinaryOr(Thread* thread, word arg); 364 static Continue doBinaryPower(Thread* thread, word arg); 365 static Continue doBinaryRshift(Thread* thread, word arg); 366 static Continue doBinarySubscr(Thread* thread, word arg); 367 static Continue doBinarySubscrDict(Thread* thread, word arg); 368 static Continue doBinarySubscrList(Thread* thread, word arg); 369 static Continue doBinarySubscrTuple(Thread* thread, word arg); 370 static Continue doBinarySubscrMonomorphic(Thread* thread, word arg); 371 static Continue doBinarySubscrPolymorphic(Thread* thread, word arg); 372 static Continue doBinarySubscrAnamorphic(Thread* thread, word arg); 373 static Continue doBinarySubtract(Thread* thread, word arg); 374 static Continue doBinaryTrueDivide(Thread* thread, word arg); 375 static Continue doBinaryXor(Thread* thread, word arg); 376 static Continue doBuildListUnpack(Thread* thread, word arg); 377 static Continue doBuildMap(Thread* thread, word arg); 378 static Continue doBuildMapUnpack(Thread* thread, word arg); 379 static Continue doBuildMapUnpackWithCall(Thread* thread, word arg); 380 static Continue doBuildSet(Thread* thread, word arg); 381 static Continue doBuildSetUnpack(Thread* thread, word arg); 382 static Continue doBuildTupleUnpack(Thread* thread, word arg); 383 static Continue doCallFinally(Thread* thread, word arg); 384 static Continue doCallFunction(Thread* thread, word arg); 385 static Continue doCallFunctionEx(Thread* thread, word arg); 386 static Continue doCallFunctionKw(Thread* thread, word arg); 387 static Continue doCallMethod(Thread* thread, word arg); 388 static Continue doCallFunctionAnamorphic(Thread* thread, word arg); 389 static Continue doCallFunctionTypeNew(Thread* thread, word arg); 390 static Continue doCallFunctionTypeInit(Thread* thread, word arg); 391 static Continue doCompareInAnamorphic(Thread* thread, word arg); 392 static Continue doCompareInStr(Thread* thread, word arg); 393 static Continue doCompareInTuple(Thread* thread, word arg); 394 static Continue doCompareInDict(Thread* thread, word arg); 395 static Continue doCompareInList(Thread* thread, word arg); 396 static Continue doCompareInMonomorphic(Thread* thread, word arg); 397 static Continue doCompareInPolymorphic(Thread* thread, word arg); 398 static Continue doCompareIs(Thread* thread, word arg); 399 static Continue doCompareIsNot(Thread* thread, word arg); 400 static Continue doCompareOp(Thread* thread, word arg); 401 static Continue doCompareOpMonomorphic(Thread* thread, word arg); 402 static Continue doCompareOpPolymorphic(Thread* thread, word arg); 403 static Continue doCompareEqSmallInt(Thread* thread, word arg); 404 static Continue doCompareGtSmallInt(Thread* thread, word arg); 405 static Continue doCompareLtSmallInt(Thread* thread, word arg); 406 static Continue doCompareGeSmallInt(Thread* thread, word arg); 407 static Continue doCompareNeSmallInt(Thread* thread, word arg); 408 static Continue doCompareLeSmallInt(Thread* thread, word arg); 409 static Continue doCompareEqStr(Thread* thread, word arg); 410 static Continue doCompareNeStr(Thread* thread, word arg); 411 static Continue doCompareOpAnamorphic(Thread* thread, word arg); 412 static Continue doDeleteAttr(Thread* thread, word arg); 413 static Continue doDeleteSubscr(Thread* thread, word arg); 414 static Continue doEndAsyncFor(Thread* thread, word arg); 415 static Continue doEndFinally(Thread* thread, word arg); 416 static Continue doForIter(Thread* thread, word arg); 417 static Continue doForIterAnamorphic(Thread* thread, word arg); 418 static Continue doForIterDict(Thread* thread, word arg); 419 static Continue doForIterGenerator(Thread* thread, word arg); 420 static Continue doForIterList(Thread* thread, word arg); 421 static Continue doForIterMonomorphic(Thread* thread, word arg); 422 static Continue doForIterPolymorphic(Thread* thread, word arg); 423 static Continue doForIterRange(Thread* thread, word arg); 424 static Continue doForIterStr(Thread* thread, word arg); 425 static Continue doForIterTuple(Thread* thread, word arg); 426 static Continue doForIterUncached(Thread* thread, word arg); 427 static Continue doFormatValue(Thread* thread, word arg); 428 static Continue doGetAiter(Thread* thread, word arg); 429 static Continue doGetAnext(Thread* thread, word arg); 430 static Continue doGetAwaitable(Thread* thread, word arg); 431 static Continue doGetIter(Thread* thread, word arg); 432 static Continue doGetYieldFromIter(Thread* thread, word arg); 433 static Continue doImportFrom(Thread* thread, word arg); 434 static Continue doImportName(Thread* thread, word arg); 435 static Continue doInplaceAdd(Thread* thread, word arg); 436 static Continue doInplaceAddSmallInt(Thread* thread, word arg); 437 static Continue doInplaceAnd(Thread* thread, word arg); 438 static Continue doInplaceFloorDivide(Thread* thread, word arg); 439 static Continue doInplaceLshift(Thread* thread, word arg); 440 static Continue doInplaceMatrixMultiply(Thread* thread, word arg); 441 static Continue doInplaceModulo(Thread* thread, word arg); 442 static Continue doInplaceMultiply(Thread* thread, word arg); 443 static Continue doInplaceOpMonomorphic(Thread* thread, word arg); 444 static Continue doInplaceOpPolymorphic(Thread* thread, word arg); 445 static Continue doInplaceOpAnamorphic(Thread* thread, word arg); 446 static Continue doInplaceOr(Thread* thread, word arg); 447 static Continue doInplacePower(Thread* thread, word arg); 448 static Continue doInplaceRshift(Thread* thread, word arg); 449 static Continue doInplaceSubtract(Thread* thread, word arg); 450 static Continue doInplaceSubSmallInt(Thread* thread, word arg); 451 static Continue doInplaceTrueDivide(Thread* thread, word arg); 452 static Continue doInplaceXor(Thread* thread, word arg); 453 static Continue doInvalidBytecode(Thread* thread, word arg); 454 static Continue doLoadAttr(Thread* thread, word arg); 455 static Continue doLoadAttrAnamorphic(Thread* thread, word arg); 456 static Continue doLoadAttrInstance(Thread* thread, word arg); 457 static Continue doLoadAttrInstanceTypeBoundMethod(Thread* thread, word arg); 458 static Continue doLoadAttrInstanceProperty(Thread* thread, word arg); 459 static Continue doLoadAttrInstanceSlotDescr(Thread* thread, word arg); 460 static Continue doLoadAttrInstanceType(Thread* thread, word arg); 461 static Continue doLoadAttrInstanceTypeDescr(Thread* thread, word arg); 462 static Continue doLoadAttrModule(Thread* thread, word arg); 463 static Continue doLoadAttrPolymorphic(Thread* thread, word arg); 464 static Continue doLoadAttrType(Thread* thread, word arg); 465 static Continue doLoadBool(Thread* thread, word arg); 466 static Continue doLoadDeref(Thread* thread, word arg); 467 static Continue doLoadFast(Thread* thread, word arg); 468 static Continue doLoadFastReverse(Thread* thread, word arg); 469 static Continue doLoadFastReverseUnchecked(Thread* thread, word arg); 470 static Continue doLoadMethod(Thread* thread, word arg); 471 static Continue doLoadMethodAnamorphic(Thread* thread, word arg); 472 static Continue doLoadMethodInstanceFunction(Thread* thread, word arg); 473 static Continue doLoadMethodModule(Thread* thread, word arg); 474 static Continue doLoadMethodPolymorphic(Thread* thread, word arg); 475 static Continue doLoadName(Thread* thread, word arg); 476 static Continue doLoadType(Thread* thread, word arg); 477 static Continue doPopExcept(Thread* thread, word arg); 478 static Continue doPopFinally(Thread* thread, word arg); 479 static Continue doRaiseVarargs(Thread* thread, word arg); 480 static Continue doReturnValue(Thread* thread, word arg); 481 static Continue doSetupWith(Thread* thread, word arg); 482 static Continue doStoreAttr(Thread* thread, word arg); 483 static Continue doStoreAttrInstance(Thread* thread, word arg); 484 static Continue doStoreAttrInstanceOverflow(Thread* thread, word arg); 485 static Continue doStoreAttrInstanceOverflowUpdate(Thread* thread, word arg); 486 static Continue doStoreAttrInstanceUpdate(Thread* thread, word arg); 487 static Continue doStoreAttrPolymorphic(Thread* thread, word arg); 488 static Continue doStoreAttrAnamorphic(Thread* thread, word arg); 489 static Continue doStoreSubscr(Thread* thread, word arg); 490 static Continue doStoreSubscrDict(Thread* thread, word arg); 491 static Continue doStoreSubscrList(Thread* thread, word arg); 492 static Continue doStoreSubscrMonomorphic(Thread* thread, word arg); 493 static Continue doStoreSubscrPolymorphic(Thread* thread, word arg); 494 static Continue doStoreSubscrAnamorphic(Thread* thread, word arg); 495 static Continue doUnaryInvert(Thread* thread, word arg); 496 static Continue doUnaryOpAnamorphic(Thread* thread, word arg); 497 static Continue doUnaryNegative(Thread* thread, word arg); 498 static Continue doUnaryNegativeSmallInt(Thread* thread, word arg); 499 static Continue doUnaryNot(Thread* thread, word arg); 500 static Continue doUnaryPositive(Thread* thread, word arg); 501 static Continue doUnpackEx(Thread* thread, word arg); 502 static Continue doUnpackSequence(Thread* thread, word arg); 503 static Continue doWithCleanupFinish(Thread* thread, word arg); 504 static Continue doWithCleanupStart(Thread* thread, word arg); 505 static Continue doYieldFrom(Thread* thread, word arg); 506 static Continue doYieldValue(Thread* thread, word arg); 507 static Continue doBuildConstKeyMap(Thread* thread, word arg); 508 static Continue doBuildList(Thread* thread, word arg); 509 static Continue doBuildSlice(Thread* thread, word arg); 510 static Continue doBuildString(Thread* thread, word arg); 511 static Continue doBuildTuple(Thread* thread, word arg); 512 static Continue doDeleteDeref(Thread* thread, word arg); 513 static Continue doDeleteFast(Thread* thread, word arg); 514 static Continue doDeleteFastReverseUnchecked(Thread* thread, word arg); 515 static Continue doDeleteGlobal(Thread* thread, word arg); 516 static Continue doDeleteName(Thread* thread, word arg); 517 static Continue doDupTop(Thread* thread, word arg); 518 static Continue doDupTopTwo(Thread* thread, word arg); 519 static Continue doImportStar(Thread* thread, word arg); 520 static Continue doJumpAbsolute(Thread* thread, word arg); 521 static Continue doJumpForward(Thread* thread, word arg); 522 static Continue doJumpIfFalseOrPop(Thread* thread, word arg); 523 static Continue doJumpIfTrueOrPop(Thread* thread, word arg); 524 static Continue doListAppend(Thread* thread, word arg); 525 static Continue doLoadBuildClass(Thread* thread, word arg); 526 static Continue doLoadClassDeref(Thread* thread, word arg); 527 static Continue doLoadClosure(Thread* thread, word arg); 528 static Continue doLoadConst(Thread* thread, word arg); 529 static Continue doLoadGlobal(Thread* thread, word arg); 530 static Continue doLoadGlobalCached(Thread* thread, word arg); 531 static Continue doLoadImmediate(Thread* thread, word arg); 532 static Continue doMakeFunction(Thread* thread, word arg); 533 static Continue doMapAdd(Thread* thread, word arg); 534 static Continue doNop(Thread* thread, word arg); 535 static Continue doPopBlock(Thread* thread, word arg); 536 static Continue doPopJumpIfFalse(Thread* thread, word arg); 537 static Continue doPopJumpIfTrue(Thread* thread, word arg); 538 static Continue doPopTop(Thread* thread, word arg); 539 static Continue doPrintExpr(Thread* thread, word arg); 540 static Continue doRotThree(Thread* thread, word arg); 541 static Continue doRotTwo(Thread* thread, word arg); 542 static Continue doRotFour(Thread* thread, word arg); 543 static Continue doSetAdd(Thread* thread, word arg); 544 static Continue doSetupAnnotations(Thread* thread, word arg); 545 static Continue doSetupAsyncWith(Thread* thread, word arg); 546 static Continue doSetupFinally(Thread* thread, word arg); 547 static Continue doStoreAnnotation(Thread* thread, word arg); 548 static Continue doStoreDeref(Thread* thread, word arg); 549 static Continue doStoreFast(Thread* thread, word arg); 550 static Continue doStoreFastReverse(Thread* thread, word arg); 551 static Continue doStoreGlobal(Thread* thread, word arg); 552 static Continue doStoreGlobalCached(Thread* thread, word arg); 553 static Continue doStoreName(Thread* thread, word arg); 554 555 // Call an interpreted function (this captures the part of the CALL_FUNCTION 556 // process after intrinsics are processed and it has been determined that the 557 // callable is an interpreted function). 558 static Continue callInterpreted(Thread* thread, word nargs, 559 RawFunction function); 560 561 // Resolve a callable object to a function (resolving `__call__` descriptors 562 // as necessary). 563 // This is a helper for `prepareCallableCall`: `prepareCallableCall` starts 564 // out with shortcuts with the common cases and only calls this function for 565 // the remaining rare cases with the expectation that this function is not 566 // inlined. 567 static PrepareCallableResult prepareCallableCallDunderCall(Thread* thread, 568 word nargs, 569 word callable_idx); 570 571 // If the given GeneratorBase is suspended at a YIELD_FROM instruction, return 572 // its subiterator. Otherwise, return None. 573 static RawObject findYieldFrom(RawGeneratorBase gen); 574 575 private: 576 // Common functionality for opcode handlers that dispatch to binary and 577 // inplace operations 578 static Continue doBinaryOperation(BinaryOp op, Thread* thread); 579 static Continue doInplaceOperation(BinaryOp op, Thread* thread); 580 static Continue doUnaryOperation(SymbolId selector, Thread* thread); 581 582 // Slow path for the FOR_ITER opcode that updates the cache at the given index 583 // when appropriate. May also be used as a non-caching slow path by passing a 584 // negative index. 585 static Continue forIterUpdateCache(Thread* thread, word arg, word cache); 586 static Continue forIter(Thread* thread, RawObject next_method, word arg); 587 588 // Slow path for isTrue check. Does a __bool__ method call, etc. 589 static RawObject isTrueSlowPath(Thread* thread, RawObject value_obj); 590 591 // Perform a method call at the end of an opcode handler. The benefit over 592 // using `callMethod1()` is that we avoid recursively starting a new 593 // interpreter loop when the target is a python function. Must only be used 594 // on objects looked up via `lookupMethod`. 595 static Continue tailcallMethod1(Thread* thread, RawObject method, 596 RawObject self); 597 598 // Call callable with `arg` parameters at the end of an opcode handler. Use 599 // this when the number of parameters is more than 2. 600 static Continue tailcall(Thread* thread, word arg); 601 602 // Call function object at frame[nargs]. The result functionc all result 603 // is pushed onto the stack. 604 static Continue tailcallFunction(Thread* thread, word nargs, 605 RawObject function_obj); 606 607 // Given a non-Function object in `callable`, attempt to normalize it to a 608 // Function by either unpacking a BoundMethod or looking up the object's 609 // __call__ method, iterating multiple times if necessary. 610 // 611 // On success, `callable` will contain the Function to call, and the return 612 // value will be a bool indicating whether or not `self` was populated with an 613 // object unpacked from a BoundMethod. 614 // 615 // On failure, Error is returned and `callable` may have been modified. 616 static RawObject prepareCallable(Thread* thread, Object* callable, 617 Object* self); 618 619 // Prepare the stack for an explode call by normalizing the callable object 620 // using prepareCallableObject(). 621 // 622 // Returns the concrete Function that should be called. 623 static RawObject prepareCallableEx(Thread* thread, word callable_idx); 624 625 // Perform a positional or keyword call. Used by doCallFunction() and 626 // doCallFunctionKw(). 627 static Continue handleCall(Thread* thread, word nargs, word callable_idx, 628 PrepareCallFunc prepare_args, 629 Function::Entry (RawFunction::*get_entry)() const); 630 631 // Call a function through its trampoline, pushing the result on the stack. 632 static Continue callTrampoline(Thread* thread, Function::Entry entry, 633 word nargs, RawObject* post_call_sp); 634 635 static Continue retryLoadAttrCached(Thread* thread, word arg, word cache); 636 static Continue retryLoadMethodCached(Thread* thread, word arg, word cache); 637 static Continue loadAttrUpdateCache(Thread* thread, word arg, word cache); 638 static Continue storeAttrUpdateCache(Thread* thread, word arg, word cache); 639 static Continue storeSubscr(Thread* thread, RawObject set_item_method); 640 static Continue callFunctionTypeNewUpdateCache(Thread* thread, word arg, 641 word cache); 642 643 static Continue loadMethodUpdateCache(Thread* thread, word arg, word cache); 644 645 using BinaryOpFallbackHandler = Continue (*)(Thread* thread, word arg, 646 BinaryOpFlags flags); 647 648 static Continue binaryOp(Thread* thread, word arg, RawObject method, 649 BinaryOpFlags flags, RawObject left, RawObject right, 650 BinaryOpFallbackHandler fallback); 651 static Continue binaryOpFallback(Thread* thread, word arg, 652 BinaryOpFlags flags); 653 654 static Continue compareOpFallback(Thread* thread, word arg, 655 BinaryOpFlags flags); 656 657 static Continue inplaceOpFallback(Thread* thread, word arg, 658 BinaryOpFlags flags); 659 660 static RawObject awaitableIter(Thread* thread, 661 const char* invalid_type_message); 662}; 663 664Interpreter* createCppInterpreter(); 665 666} // namespace py