this repo has no description
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