text: /* Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) */
  #pragma once
  
  #include "handles-decl.h"
  #include "objects.h"
  
  namespace py {
  
  // Define the set of bytecodes.
  //
  // Except for the *_CACHED instructions at the end of the list, these are all
  // taken directly from CPython. The cached bytecodes perform the same operation
  // as their CPython counterpart, but do it more quickly using an inline cache.
  //
  // `FOREACH_BYTECODE` calls V for each bytecode with 3 arguments:
  //   1. The opcode's name.
  //   2. The opcode's numeric value.
  //   3. The opcode handler's name.
  #define FOREACH_BYTECODE(V)                                                    \
    V(UNUSED_BYTECODE_0, 0, doInvalidBytecode)                                   \
    V(POP_TOP, 1, doPopTop)                                                      \
    V(ROT_TWO, 2, doRotTwo)                                                      \
    V(ROT_THREE, 3, doRotThree)                                                  \
    V(DUP_TOP, 4, doDupTop)                                                      \
    V(DUP_TOP_TWO, 5, doDupTopTwo)                                               \
    V(ROT_FOUR, 6, doRotFour)                                                    \
    V(UNUSED_BYTECODE_7, 7, doInvalidBytecode)                                   \
    V(UNUSED_BYTECODE_8, 8, doInvalidBytecode)                                   \
    V(NOP, 9, doNop)                                                             \
    V(UNARY_POSITIVE, 10, doUnaryPositive)                                       \
    V(UNARY_NEGATIVE, 11, doUnaryNegative)                                       \
    V(UNARY_NOT, 12, doUnaryNot)                                                 \
    V(UNUSED_BYTECODE_13, 13, doInvalidBytecode)                                 \
    V(UNUSED_BYTECODE_14, 14, doInvalidBytecode)                                 \
    V(UNARY_INVERT, 15, doUnaryInvert)                                           \
    V(BINARY_MATRIX_MULTIPLY, 16, doBinaryMatrixMultiply)                        \
    V(INPLACE_MATRIX_MULTIPLY, 17, doInplaceMatrixMultiply)                      \
    V(UNUSED_BYTECODE_18, 18, doInvalidBytecode)                                 \
    V(BINARY_POWER, 19, doBinaryPower)                                           \
    V(BINARY_MULTIPLY, 20, doBinaryMultiply)                                     \
    V(UNUSED_BYTECODE_21, 21, doInvalidBytecode)                                 \
    V(BINARY_MODULO, 22, doBinaryModulo)                                         \
    V(BINARY_ADD, 23, doBinaryAdd)                                               \
    V(BINARY_SUBTRACT, 24, doBinarySubtract)                                     \
    V(BINARY_SUBSCR, 25, doBinarySubscr)                                         \
    V(BINARY_FLOOR_DIVIDE, 26, doBinaryFloorDivide)                              \
    V(BINARY_TRUE_DIVIDE, 27, doBinaryTrueDivide)                                \
    V(INPLACE_FLOOR_DIVIDE, 28, doInplaceFloorDivide)                            \
    V(INPLACE_TRUE_DIVIDE, 29, doInplaceTrueDivide)                              \
    V(UNUSED_BYTECODE_30, 30, doInvalidBytecode)                                 \
    V(UNUSED_BYTECODE_31, 31, doInvalidBytecode)                                 \
    V(UNUSED_BYTECODE_32, 32, doInvalidBytecode)                                 \
    V(UNUSED_BYTECODE_33, 33, doInvalidBytecode)                                 \
    V(UNUSED_BYTECODE_34, 34, doInvalidBytecode)                                 \
    V(UNUSED_BYTECODE_35, 35, doInvalidBytecode)                                 \
    V(UNUSED_BYTECODE_36, 36, doInvalidBytecode)                                 \
    V(UNUSED_BYTECODE_37, 37, doInvalidBytecode)                                 \
    V(UNUSED_BYTECODE_38, 38, doInvalidBytecode)                                 \
    V(UNUSED_BYTECODE_39, 39, doInvalidBytecode)                                 \
    V(UNUSED_BYTECODE_40, 40, doInvalidBytecode)                                 \
    V(UNUSED_BYTECODE_41, 41, doInvalidBytecode)                                 \
    V(UNUSED_BYTECODE_42, 42, doInvalidBytecode)                                 \
    V(UNUSED_BYTECODE_43, 43, doInvalidBytecode)                                 \
    V(UNUSED_BYTECODE_44, 44, doInvalidBytecode)                                 \
    V(UNUSED_BYTECODE_45, 45, doInvalidBytecode)                                 \
    V(UNUSED_BYTECODE_46, 46, doInvalidBytecode)                                 \
    V(UNUSED_BYTECODE_47, 47, doInvalidBytecode)                                 \
    V(LOAD_BOOL, 48, doLoadBool)                                                 \
    V(LOAD_FAST_REVERSE_UNCHECKED, 49, doLoadFastReverseUnchecked)               \
    V(GET_AITER, 50, doGetAiter)                                                 \
    V(GET_ANEXT, 51, doGetAnext)                                                 \
    V(BEFORE_ASYNC_WITH, 52, doBeforeAsyncWith)                                  \
    V(BEGIN_FINALLY, 53, doBeginFinally)                                         \
    V(END_ASYNC_FOR, 54, doEndAsyncFor)                                          \
    V(INPLACE_ADD, 55, doInplaceAdd)                                             \
    V(INPLACE_SUBTRACT, 56, doInplaceSubtract)                                   \
    V(INPLACE_MULTIPLY, 57, doInplaceMultiply)                                   \
    V(UNUSED_BYTECODE_58, 58, doInvalidBytecode)                                 \
    V(INPLACE_MODULO, 59, doInplaceModulo)                                       \
    V(STORE_SUBSCR, 60, doStoreSubscr)                                           \
    V(DELETE_SUBSCR, 61, doDeleteSubscr)                                         \
    V(BINARY_LSHIFT, 62, doBinaryLshift)                                         \
    V(BINARY_RSHIFT, 63, doBinaryRshift)                                         \
    V(BINARY_AND, 64, doBinaryAnd)                                               \
    V(BINARY_XOR, 65, doBinaryXor)                                               \
    V(BINARY_OR, 66, doBinaryOr)                                                 \
    V(INPLACE_POWER, 67, doInplacePower)                                         \
    V(GET_ITER, 68, doGetIter)                                                   \
    V(GET_YIELD_FROM_ITER, 69, doGetYieldFromIter)                               \
    V(PRINT_EXPR, 70, doPrintExpr)                                               \
    V(LOAD_BUILD_CLASS, 71, doLoadBuildClass)                                    \
    V(YIELD_FROM, 72, doYieldFrom)                                               \
    V(GET_AWAITABLE, 73, doGetAwaitable)                                         \
    V(UNUSED_BYTECODE_74, 74, doInvalidBytecode)                                 \
    V(INPLACE_LSHIFT, 75, doInplaceLshift)                                       \
    V(INPLACE_RSHIFT, 76, doInplaceRshift)                                       \
    V(INPLACE_AND, 77, doInplaceAnd)                                             \
    V(INPLACE_XOR, 78, doInplaceXor)                                             \
    V(INPLACE_OR, 79, doInplaceOr)                                               \
    V(UNUSED_BYTECODE_80, 80, doInvalidBytecode)                                 \
    V(WITH_CLEANUP_START, 81, doWithCleanupStart)                                \
    V(WITH_CLEANUP_FINISH, 82, doWithCleanupFinish)                              \
    V(RETURN_VALUE, 83, doReturnValue)                                           \
    V(IMPORT_STAR, 84, doImportStar)                                             \
    V(SETUP_ANNOTATIONS, 85, doSetupAnnotations)                                 \
    V(YIELD_VALUE, 86, doYieldValue)                                             \
    V(POP_BLOCK, 87, doPopBlock)                                                 \
    V(END_FINALLY, 88, doEndFinally)                                             \
    V(POP_EXCEPT, 89, doPopExcept)                                               \
    V(STORE_NAME, 90, doStoreName)                                               \
    V(DELETE_NAME, 91, doDeleteName)                                             \
    V(UNPACK_SEQUENCE, 92, doUnpackSequence)                                     \
    V(FOR_ITER, 93, doForIter)                                                   \
    V(UNPACK_EX, 94, doUnpackEx)                                                 \
    V(STORE_ATTR, 95, doStoreAttr)                                               \
    V(DELETE_ATTR, 96, doDeleteAttr)                                             \
    V(STORE_GLOBAL, 97, doStoreGlobal)                                           \
    V(DELETE_GLOBAL, 98, doDeleteGlobal)                                         \
    V(UNUSED_BYTECODE_99, 99, doInvalidBytecode)                                 \
    V(LOAD_CONST, 100, doLoadConst)                                              \
    V(LOAD_NAME, 101, doLoadName)                                                \
    V(BUILD_TUPLE, 102, doBuildTuple)                                            \
    V(BUILD_LIST, 103, doBuildList)                                              \
    V(BUILD_SET, 104, doBuildSet)                                                \
    V(BUILD_MAP, 105, doBuildMap)                                                \
    V(LOAD_ATTR, 106, doLoadAttr)                                                \
    V(COMPARE_OP, 107, doCompareOp)                                              \
    V(IMPORT_NAME, 108, doImportName)                                            \
    V(IMPORT_FROM, 109, doImportFrom)                                            \
    V(JUMP_FORWARD, 110, doJumpForward)                                          \
    V(JUMP_IF_FALSE_OR_POP, 111, doJumpIfFalseOrPop)                             \
    V(JUMP_IF_TRUE_OR_POP, 112, doJumpIfTrueOrPop)                               \
    V(JUMP_ABSOLUTE, 113, doJumpAbsolute)                                        \
    V(POP_JUMP_IF_FALSE, 114, doPopJumpIfFalse)                                  \
    V(POP_JUMP_IF_TRUE, 115, doPopJumpIfTrue)                                    \
    V(LOAD_GLOBAL, 116, doLoadGlobal)                                            \
    V(UNUSED_BYTECODE_117, 117, doInvalidBytecode)                               \
    V(UNUSED_BYTECODE_118, 118, doInvalidBytecode)                               \
    V(UNUSED_BYTECODE_119, 119, doInvalidBytecode)                               \
    V(UNUSED_BYTECODE_120, 120, doInvalidBytecode)                               \
    V(UNUSED_BYTECODE_121, 121, doInvalidBytecode)                               \
    V(SETUP_FINALLY, 122, doSetupFinally)                                        \
    V(UNUSED_BYTECODE_123, 123, doInvalidBytecode)                               \
    V(LOAD_FAST, 124, doLoadFast)                                                \
    V(STORE_FAST, 125, doStoreFast)                                              \
    V(DELETE_FAST, 126, doDeleteFast)                                            \
    V(UNUSED_BYTECODE_127, 127, doInvalidBytecode)                               \
    V(UNUSED_BYTECODE_128, 128, doInvalidBytecode)                               \
    V(UNUSED_BYTECODE_129, 129, doInvalidBytecode)                               \
    V(RAISE_VARARGS, 130, doRaiseVarargs)                                        \
    V(CALL_FUNCTION, 131, doCallFunction)                                        \
    V(MAKE_FUNCTION, 132, doMakeFunction)                                        \
    V(BUILD_SLICE, 133, doBuildSlice)                                            \
    V(UNUSED_BYTECODE_134, 134, doInvalidBytecode)                               \
    V(LOAD_CLOSURE, 135, doLoadClosure)                                          \
    V(LOAD_DEREF, 136, doLoadDeref)                                              \
    V(STORE_DEREF, 137, doStoreDeref)                                            \
    V(DELETE_DEREF, 138, doDeleteDeref)                                          \
    V(UNUSED_BYTECODE_139, 139, doInvalidBytecode)                               \
    V(UNUSED_BYTECODE_140, 140, doInvalidBytecode)                               \
    V(CALL_FUNCTION_KW, 141, doCallFunctionKw)                                   \
    V(CALL_FUNCTION_EX, 142, doCallFunctionEx)                                   \
    V(SETUP_WITH, 143, doSetupWith)                                              \
    V(EXTENDED_ARG, 144, doInvalidBytecode)                                      \
    V(LIST_APPEND, 145, doListAppend)                                            \
    V(SET_ADD, 146, doSetAdd)                                                    \
    V(MAP_ADD, 147, doMapAdd)                                                    \
    V(LOAD_CLASSDEREF, 148, doLoadClassDeref)                                    \
    V(BUILD_LIST_UNPACK, 149, doBuildListUnpack)                                 \
    V(BUILD_MAP_UNPACK, 150, doBuildMapUnpack)                                   \
    V(BUILD_MAP_UNPACK_WITH_CALL, 151, doBuildMapUnpackWithCall)                 \
    V(BUILD_TUPLE_UNPACK, 152, doBuildTupleUnpack)                               \
    V(BUILD_SET_UNPACK, 153, doBuildSetUnpack)                                   \
    V(SETUP_ASYNC_WITH, 154, doSetupAsyncWith)                                   \
    V(FORMAT_VALUE, 155, doFormatValue)                                          \
    V(BUILD_CONST_KEY_MAP, 156, doBuildConstKeyMap)                              \
    V(BUILD_STRING, 157, doBuildString)                                          \
    V(BUILD_TUPLE_UNPACK_WITH_CALL, 158, doBuildTupleUnpack)                     \
    V(UNUSED_BYTECODE_159, 159, doInvalidBytecode)                               \
    V(LOAD_METHOD, 160, doLoadMethod)                                            \
    V(CALL_METHOD, 161, doCallMethod)                                            \
    V(CALL_FINALLY, 162, doCallFinally)                                          \
    V(POP_FINALLY, 163, doPopFinally)                                            \
    V(UNUSED_BYTECODE_164, 164, doInvalidBytecode)                               \
    V(UNUSED_BYTECODE_165, 165, doInvalidBytecode)                               \
    V(UNUSED_BYTECODE_166, 166, doInvalidBytecode)                               \
    V(UNUSED_BYTECODE_167, 167, doInvalidBytecode)                               \
    V(UNUSED_BYTECODE_168, 168, doInvalidBytecode)                               \
    V(UNUSED_BYTECODE_169, 169, doInvalidBytecode)                               \
    V(UNUSED_BYTECODE_170, 170, doInvalidBytecode)                               \
    V(UNUSED_BYTECODE_171, 171, doInvalidBytecode)                               \
    V(UNUSED_BYTECODE_172, 172, doInvalidBytecode)                               \
    V(UNUSED_BYTECODE_173, 173, doInvalidBytecode)                               \
    V(UNUSED_BYTECODE_174, 174, doInvalidBytecode)                               \
    V(UNUSED_BYTECODE_175, 175, doInvalidBytecode)                               \
    V(CALL_FUNCTION_TYPE_NEW, 176, doCallFunctionTypeNew)                        \
    V(CALL_FUNCTION_ANAMORPHIC, 177, doCallFunctionAnamorphic)                   \
    V(COMPARE_NE_STR, 178, doCompareNeStr)                                       \
    V(FOR_ITER_GENERATOR, 179, doForIterGenerator)                               \
    V(STORE_SUBSCR_DICT, 180, doStoreSubscrDict)                                 \
    V(BINARY_MUL_SMALLINT, 181, doBinaryMulSmallInt)                             \
    V(BINARY_SUBSCR_DICT, 182, doBinarySubscrDict)                               \
    V(BINARY_SUBSCR_TUPLE, 183, doBinarySubscrTuple)                             \
    V(INPLACE_SUB_SMALLINT, 184, doInplaceSubSmallInt)                           \
    V(STORE_SUBSCR_LIST, 185, doStoreSubscrList)                                 \
    V(BINARY_SUBSCR_LIST, 186, doBinarySubscrList)                               \
    V(LOAD_ATTR_INSTANCE_SLOT_DESCR, 187, doLoadAttrInstanceSlotDescr)           \
    V(COMPARE_IN_LIST, 188, doCompareInList)                                     \
    V(COMPARE_IN_DICT, 189, doCompareInDict)                                     \
    V(COMPARE_IN_TUPLE, 190, doCompareInTuple)                                   \
    V(COMPARE_IN_STR, 191, doCompareInStr)                                       \
    V(COMPARE_IN_POLYMORPHIC, 192, doCompareInPolymorphic)                       \
    V(COMPARE_IN_MONOMORPHIC, 193, doCompareInMonomorphic)                       \
    V(COMPARE_IN_ANAMORPHIC, 194, doCompareInAnamorphic)                         \
    V(BINARY_FLOORDIV_SMALLINT, 195, doBinaryFloordivSmallInt)                   \
    V(BINARY_AND_SMALLINT, 196, doBinaryAndSmallInt)                             \
    V(FOR_ITER_STR, 197, doForIterStr)                                           \
    V(FOR_ITER_RANGE, 198, doForIterRange)                                       \
    V(FOR_ITER_TUPLE, 199, doForIterTuple)                                       \
    V(FOR_ITER_DICT, 200, doForIterDict)                                         \
    V(FOR_ITER_LIST, 201, doForIterList)                                         \
    V(INPLACE_ADD_SMALLINT, 202, doInplaceAddSmallInt)                           \
    V(COMPARE_EQ_STR, 203, doCompareEqStr)                                       \
    V(COMPARE_LE_SMALLINT, 204, doCompareLeSmallInt)                             \
    V(COMPARE_NE_SMALLINT, 205, doCompareNeSmallInt)                             \
    V(COMPARE_GE_SMALLINT, 206, doCompareGeSmallInt)                             \
    V(COMPARE_LT_SMALLINT, 207, doCompareLtSmallInt)                             \
    V(COMPARE_GT_SMALLINT, 208, doCompareGtSmallInt)                             \
    V(COMPARE_EQ_SMALLINT, 209, doCompareEqSmallInt)                             \
    V(BINARY_OR_SMALLINT, 210, doBinaryOrSmallInt)                               \
    V(BINARY_SUB_SMALLINT, 211, doBinarySubSmallInt)                             \
    V(BINARY_ADD_SMALLINT, 212, doBinaryAddSmallInt)                             \
    V(INPLACE_OP_POLYMORPHIC, 213, doInplaceOpPolymorphic)                       \
    V(INPLACE_OP_MONOMORPHIC, 214, doInplaceOpMonomorphic)                       \
    V(COMPARE_OP_POLYMORPHIC, 215, doCompareOpPolymorphic)                       \
    V(COMPARE_OP_MONOMORPHIC, 216, doCompareOpMonomorphic)                       \
    V(BINARY_OP_POLYMORPHIC, 217, doBinaryOpPolymorphic)                         \
    V(BINARY_OP_MONOMORPHIC, 218, doBinaryOpMonomorphic)                         \
    V(STORE_SUBSCR_POLYMORPHIC, 219, doStoreSubscrPolymorphic)                   \
    V(STORE_SUBSCR_MONOMORPHIC, 220, doStoreSubscrMonomorphic)                   \
    V(FOR_ITER_POLYMORPHIC, 221, doForIterPolymorphic)                           \
    V(FOR_ITER_MONOMORPHIC, 222, doForIterMonomorphic)                           \
    V(BINARY_SUBSCR_POLYMORPHIC, 223, doBinarySubscrPolymorphic)                 \
    V(BINARY_SUBSCR_MONOMORPHIC, 224, doBinarySubscrMonomorphic)                 \
    V(STORE_ATTR_INSTANCE_OVERFLOW_UPDATE, 225,                                  \
      doStoreAttrInstanceOverflowUpdate)                                         \
    V(STORE_ATTR_INSTANCE_OVERFLOW, 226, doStoreAttrInstanceOverflow)            \
    V(STORE_ATTR_INSTANCE, 227, doStoreAttrInstance)                             \
    V(STORE_ATTR_POLYMORPHIC, 228, doStoreAttrPolymorphic)                       \
    V(LOAD_ATTR_POLYMORPHIC, 229, doLoadAttrPolymorphic)                         \
    V(LOAD_ATTR_INSTANCE_TYPE_BOUND_METHOD, 230,                                 \
      doLoadAttrInstanceTypeBoundMethod)                                         \
    V(LOAD_ATTR_INSTANCE, 231, doLoadAttrInstance)                               \
    V(LOAD_METHOD_POLYMORPHIC, 232, doLoadMethodPolymorphic)                     \
    V(LOAD_METHOD_INSTANCE_FUNCTION, 233, doLoadMethodInstanceFunction)          \
    V(STORE_SUBSCR_ANAMORPHIC, 234, doStoreSubscrAnamorphic)                     \
    V(LOAD_ATTR_INSTANCE_TYPE, 235, doLoadAttrInstanceType)                      \
    V(LOAD_ATTR_INSTANCE_TYPE_DESCR, 236, doLoadAttrInstanceTypeDescr)           \
    V(LOAD_ATTR_INSTANCE_PROPERTY, 237, doLoadAttrInstanceProperty)              \
    V(STORE_ATTR_INSTANCE_UPDATE, 238, doStoreAttrInstanceUpdate)                \
    V(LOAD_ATTR_TYPE, 239, doLoadAttrType)                                       \
    V(LOAD_ATTR_MODULE, 240, doLoadAttrModule)                                   \
    V(COMPARE_IS_NOT, 241, doCompareIsNot)                                       \
    V(COMPARE_IS, 242, doCompareIs)                                              \
    V(LOAD_IMMEDIATE, 243, doLoadImmediate)                                      \
    V(STORE_FAST_REVERSE, 244, doStoreFastReverse)                               \
    V(LOAD_FAST_REVERSE, 245, doLoadFastReverse)                                 \
    V(LOAD_METHOD_ANAMORPHIC, 246, doLoadMethodAnamorphic)                       \
    V(STORE_GLOBAL_CACHED, 247, doStoreGlobalCached)                             \
    V(LOAD_GLOBAL_CACHED, 248, doLoadGlobalCached)                               \
    V(FOR_ITER_ANAMORPHIC, 249, doForIterAnamorphic)                             \
    V(COMPARE_OP_ANAMORPHIC, 250, doCompareOpAnamorphic)                         \
    V(INPLACE_OP_ANAMORPHIC, 251, doInplaceOpAnamorphic)                         \
    V(BINARY_OP_ANAMORPHIC, 252, doBinaryOpAnamorphic)                           \
    V(BINARY_SUBSCR_ANAMORPHIC, 253, doBinarySubscrAnamorphic)                   \
    V(STORE_ATTR_ANAMORPHIC, 254, doStoreAttrAnamorphic)                         \
    V(LOAD_ATTR_ANAMORPHIC, 255, doLoadAttrAnamorphic)
  
  const word kNumBytecodes = 256;
  
  enum Bytecode {
  #define ENUM(name, value, handler) name = value,
    FOREACH_BYTECODE(ENUM)
  #undef ENUM
  };
  
  enum CompareOp {
    LT = 0,
    LE = 1,
    EQ = 2,
    NE = 3,
    GT = 4,
    GE = 5,
    IN,
    NOT_IN,
    IS,
    IS_NOT,
    EXC_MATCH,
    BAD
  };
  
  enum class FormatValueConv {
    kNone = 0,
    kStr = 1,
    kRepr = 2,
    kAscii = 3,
  };
  
  const word kFormatValueConvMask = 0x3;
  const word kFormatValueHasSpecBit = 0x4;
  
  enum MakeFunctionFlag {
    DEFAULT = 0x01,
    DEFAULT_KW = 0x02,
    ANNOTATION_DICT = 0x04,
    CLOSURE = 0x08,
  };
  
  enum CallFunctionExFlag {
    VAR_KEYWORDS = 0x01,
  };
  
  // Size of opcode + argument in bytecode (called `_Py_CODEUNIT` in cpython).
  const word kCompilerCodeUnitSize = 2;
  const word kCodeUnitSize = 4;
  // TODO(T84723098): Remove kCodeUnitScale and kCodeUnitScaleLog2 and all the
  // places that scale PCs
  const word kCodeUnitScale = kCodeUnitSize / kCompilerCodeUnitSize;
  const word kCodeUnitScaleLog2 = 1;
  
  extern const char* const kBytecodeNames[];
  
  struct BytecodeOp {
    Bytecode bc;
    int32_t arg;
    uint16_t cache;
  };
  
  BytecodeOp nextBytecodeOp(const MutableBytes& bytecode, word* index);
  
  // Return the opcode in the bytes object at the given opcode index. For
  // example, in the following code:
  //   LOAD_ATTR,   arg,
  //   LOAD_GLOBAL, arg,
  // bytecodeAt(..., 0) would return LOAD_ATTR and
  // bytecodeAt(..., 1) would return LOAD_GLOBAL.
  word bytecodeLength(const Bytes& bytecode);
  Bytecode bytecodeOpAt(const Bytes& bytecode, word index);
  byte bytecodeArgAt(const Bytes& bytecode, word index);
  
  // Return the opcode in the rewritten bytes object at the given opcode index.
  // For example, in the following code:
  //   LOAD_ATTR,   arg,
  //   LOAD_GLOBAL_CACHED, arg,
  // rewrittenBytecodeAt(..., 0) would return LOAD_ATTR and
  // rewrittenBytecodeAt(..., 1) would return LOAD_GLOBAL_CACHED.
  word rewrittenBytecodeLength(const MutableBytes& bytecode);
  Bytecode rewrittenBytecodeOpAt(const MutableBytes& bytecode, word index);
  void rewrittenBytecodeOpAtPut(const MutableBytes& bytecode, word index,
                                Bytecode op);
  byte rewrittenBytecodeArgAt(const MutableBytes& bytecode, word index);
  void rewrittenBytecodeArgAtPut(const MutableBytes& bytecode, word index,
                                 byte arg);
  uint16_t rewrittenBytecodeCacheAt(const MutableBytes& bytecode, word index);
  void rewrittenBytecodeCacheAtPut(const MutableBytes& bytecode, word index,
                                   uint16_t cache);
  
  inline bool isByteCodeWithCache(const Bytecode bc) {
    // TODO(T45720638): Add all caching opcodes here once they are supported for
    // cache invalidation.
    switch (bc) {
      case BINARY_OP_MONOMORPHIC:
      case BINARY_OP_POLYMORPHIC:
      case BINARY_OP_ANAMORPHIC:
      case BINARY_SUBSCR_ANAMORPHIC:
      case BINARY_SUBSCR_MONOMORPHIC:
      case BINARY_SUBSCR_POLYMORPHIC:
      case COMPARE_OP_MONOMORPHIC:
      case COMPARE_OP_POLYMORPHIC:
      case COMPARE_OP_ANAMORPHIC:
      case CALL_FUNCTION_TYPE_NEW:
      case FOR_ITER_MONOMORPHIC:
      case FOR_ITER_POLYMORPHIC:
      case FOR_ITER_ANAMORPHIC:
      case INPLACE_OP_MONOMORPHIC:
      case INPLACE_OP_POLYMORPHIC:
      case INPLACE_OP_ANAMORPHIC:
      case LOAD_ATTR_INSTANCE:
      case LOAD_ATTR_INSTANCE_PROPERTY:
      case LOAD_ATTR_INSTANCE_SLOT_DESCR:
      case LOAD_ATTR_INSTANCE_TYPE:
      case LOAD_ATTR_INSTANCE_TYPE_BOUND_METHOD:
      case LOAD_ATTR_INSTANCE_TYPE_DESCR:
      case LOAD_ATTR_MODULE:
      case LOAD_ATTR_TYPE:
      case LOAD_ATTR_ANAMORPHIC:
      case LOAD_METHOD_ANAMORPHIC:
      case LOAD_METHOD_INSTANCE_FUNCTION:
      case LOAD_METHOD_POLYMORPHIC:
      case STORE_ATTR_INSTANCE:
      case STORE_ATTR_INSTANCE_OVERFLOW:
      case STORE_ATTR_INSTANCE_OVERFLOW_UPDATE:
      case STORE_ATTR_INSTANCE_UPDATE:
      case STORE_ATTR_POLYMORPHIC:
      case STORE_ATTR_ANAMORPHIC:
      case STORE_SUBSCR_ANAMORPHIC:
        return true;
      default:
        return false;
    }
  }
  
  // Convert an immediate RawObject into a byte, and back to the original
  // object. If the object fits in a byte,
  // objectFromOparg(opargFromObject(obj) == obj will hold.
  int8_t opargFromObject(RawObject object);
  
  inline RawObject objectFromOparg(word arg) {
    return RawObject(static_cast<uword>(static_cast<int8_t>(arg)));
  }
  
  // Expand kCompilerCodeUnitSize bytecode to kCodeUnitSize bytecode, leaving all
  // opcodes and arguments intact.
  RawObject expandBytecode(Thread* thread, const Bytes& bytecode);
  
  // Prepares bytecode for caching: Adds a rewritten variant of the bytecode to
  // `function`. It has the arguments of opcodes that use the cache replaced with
  // a cache index. The previous arguments are moved to a separate tuple and can
  // be retrieved with `icOriginalArg()`. Also adds a correctly sized `caches`
  // tuple to `function`.
  void rewriteBytecode(Thread* thread, const Function& function);
  
  }  // namespace py
  