in Jit/hir/builder.cpp [377:450]
static bool should_snapshot(
const BytecodeInstruction& bci,
bool is_in_async_for_header_block) {
switch (bci.opcode()) {
// These instructions conditionally alter the operand stack based on which
// branch is taken, thus we cannot safely take a snapshot in the same basic
// block. They're also control instructions, so snapshotting in the same
// basic block doesn't make sense anyway.
case FOR_ITER:
case JUMP_IF_FALSE_OR_POP:
case JUMP_IF_NONZERO_OR_POP:
case JUMP_IF_TRUE_OR_POP:
case JUMP_IF_ZERO_OR_POP:
// These are all control instructions. Taking a snapshot after them in the
// same basic block doesn't make sense, as control immediately transfers
// to another basic block.
case BEGIN_FINALLY:
case CALL_FINALLY:
case END_FINALLY:
case JUMP_ABSOLUTE:
case JUMP_FORWARD:
case POP_JUMP_IF_FALSE:
case POP_JUMP_IF_TRUE:
case POP_JUMP_IF_ZERO:
case POP_JUMP_IF_NONZERO:
case RETURN_PRIMITIVE:
case RETURN_VALUE:
case RAISE_VARARGS:
// These instructions only modify frame state and are always safe to
// replay. We don't snapshot these in order to limit the amount of
// unnecessary metadata in the lowered IR.
case CHECK_ARGS:
case CONVERT_PRIMITIVE:
case DUP_TOP:
case DUP_TOP_TWO:
case EXTENDED_ARG:
case INT_LOAD_CONST_OLD:
case LOAD_CLOSURE:
case LOAD_CONST:
case LOAD_FAST:
case LOAD_LOCAL:
case NOP:
case POP_FINALLY:
case POP_TOP:
case PRIMITIVE_BOX:
case PRIMITIVE_LOAD_CONST:
case PRIMITIVE_UNARY_OP:
case PRIMITIVE_UNBOX:
case REFINE_TYPE:
case ROT_FOUR:
case ROT_THREE:
case ROT_TWO:
case STORE_FAST:
case STORE_LOCAL: {
return false;
}
// The `is` and `is not` comparison operators are implemented using pointer
// equality. They are always safe to replay.
case COMPARE_OP: {
auto op = static_cast<CompareOp>(bci.oparg());
return (op != CompareOp::kIs) && (op != CompareOp::kIsNot);
}
// In an async-for header block YIELD_FROM controls whether we end the loop
case YIELD_FROM: {
return !is_in_async_for_header_block;
}
// Take a snapshot after translating all other bytecode instructions. This
// may generate unnecessary deoptimization metadata but will always be
// correct.
default: {
return true;
}
}
}