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;
}
}
}