void SummaryBuilder::analyze_instruction_effects()

in opt/object-sensitive-dce/SideEffectSummary.cpp [81:205]


void SummaryBuilder::analyze_instruction_effects(
    const ptrs::Environment& env,
    const reaching_defs::Environment& reaching_def_env,
    const IRInstruction* insn,
    Summary* summary) {
  auto init_class = !!m_init_classes_with_side_effects.refine(
      get_init_class_type_demand(insn));
  if (init_class) {
    summary->effects |= EFF_INIT_CLASS;
  }

  auto op = insn->opcode();
  switch (op) {
  case OPCODE_THROW: {
    summary->effects |= EFF_THROWS;
    break;
  }
  case OPCODE_MONITOR_ENTER:
  case OPCODE_MONITOR_EXIT: {
    summary->effects |= EFF_LOCKS;
    break;
  }

  case OPCODE_SGET:
  case OPCODE_SGET_WIDE:
  case OPCODE_SGET_BOOLEAN:
  case OPCODE_SGET_BYTE:
  case OPCODE_SGET_CHAR:
  case OPCODE_SGET_SHORT:
  case OPCODE_SGET_OBJECT: {
    summary->may_read_external = true;
    break;
  }

  case OPCODE_IGET:
  case OPCODE_IGET_WIDE:
  case OPCODE_IGET_BOOLEAN:
  case OPCODE_IGET_BYTE:
  case OPCODE_IGET_CHAR:
  case OPCODE_IGET_SHORT:
  case OPCODE_IGET_OBJECT:

  case OPCODE_AGET:
  case OPCODE_AGET_WIDE:
  case OPCODE_AGET_BOOLEAN:
  case OPCODE_AGET_BYTE:
  case OPCODE_AGET_CHAR:
  case OPCODE_AGET_SHORT:
  case OPCODE_AGET_OBJECT: {
    if (m_analyze_external_reads) {
      auto def = reaching_def_env.get(insn->src(0));
      if (def.is_top() ||
          std::any_of(def.elements().begin(), def.elements().end(),
                      [&](auto insn) {
                        return !opcode::is_a_load_param(insn->opcode());
                      })) {
        summary->may_read_external = true;
      }
    } else {
      summary->may_read_external = true;
    }
    break;
  }

  case OPCODE_SPUT:
  case OPCODE_SPUT_WIDE:
  case OPCODE_SPUT_BOOLEAN:
  case OPCODE_SPUT_BYTE:
  case OPCODE_SPUT_CHAR:
  case OPCODE_SPUT_SHORT:
  case OPCODE_SPUT_OBJECT: {
    summary->effects |= EFF_WRITE_MAY_ESCAPE;
    break;
  }
  case OPCODE_IPUT:
  case OPCODE_IPUT_WIDE:
  case OPCODE_IPUT_BOOLEAN:
  case OPCODE_IPUT_BYTE:
  case OPCODE_IPUT_CHAR:
  case OPCODE_IPUT_SHORT:
  case OPCODE_IPUT_OBJECT:

  case OPCODE_APUT:
  case OPCODE_APUT_WIDE:
  case OPCODE_APUT_BOOLEAN:
  case OPCODE_APUT_BYTE:
  case OPCODE_APUT_CHAR:
  case OPCODE_APUT_SHORT:
  case OPCODE_APUT_OBJECT: {
    classify_heap_write(env, insn->src(1), summary);
    break;
  }

  case OPCODE_FILL_ARRAY_DATA: {
    classify_heap_write(env, insn->src(0), summary);
    break;
  }

  case OPCODE_INVOKE_SUPER:
  case OPCODE_INVOKE_INTERFACE: {
    TRACE(OSDCE, 3, "Unknown invoke: %s", SHOW(insn));
    summary->effects |= EFF_UNKNOWN_INVOKE;
    break;
  }
  case OPCODE_INVOKE_STATIC:
  case OPCODE_INVOKE_DIRECT:
  case OPCODE_INVOKE_VIRTUAL: {
    if (m_invoke_to_summary_cmap.count(insn)) {
      const auto& callee_summary = m_invoke_to_summary_cmap.at(insn);
      summary->effects |= callee_summary.effects;
      summary->may_read_external |= callee_summary.may_read_external;
      for (auto idx : callee_summary.modified_params) {
        classify_heap_write(env, insn->src(idx), summary);
      }
    } else {
      TRACE(OSDCE, 3, "Unknown invoke: %s", SHOW(insn));
      summary->effects |= EFF_UNKNOWN_INVOKE;
    }
    break;
  }
  default: {
    break;
  }
  }
}