in source/MethodContext.cpp [47:123]
Model MethodContext::model_at_callsite(
const CallTarget& call_target,
const Position* position,
const std::vector<const DexType * MT_NULLABLE>& source_register_types,
const std::vector<std::optional<std::string>>& source_constant_arguments)
const {
auto* caller = method();
LOG_OR_DUMP(
this,
5,
"Getting model for {} call `{}`",
(call_target.is_virtual() ? "virtual" : "static"),
show(call_target.resolved_base_callee()));
if (!call_target.resolved()) {
return Model(
/* method */ nullptr,
context_,
Model::Mode::SkipAnalysis | Model::Mode::AddViaObscureFeature |
Model::Mode::TaintInTaintOut);
}
if (call_target.is_virtual()) {
auto cached = callsite_model_cache_.find(CacheKey{call_target, position});
if (cached != callsite_model_cache_.end()) {
return cached->second;
}
}
auto model = registry.get(call_target.resolved_base_callee())
.at_callsite(
caller,
position,
context_,
source_register_types,
source_constant_arguments);
if (!call_target.is_virtual()) {
return model;
}
if (model.no_join_virtual_overrides()) {
LOG_OR_DUMP(
this,
5,
"Not joining at call-site for method `{}`",
show(call_target.resolved_base_callee()));
return model;
}
LOG_OR_DUMP(
this,
5,
"Initial model for `{}`: {}",
show(call_target.resolved_base_callee()),
model);
for (const auto* override : call_target.overrides()) {
auto override_model = registry.get(override).at_callsite(
caller,
position,
context_,
source_register_types,
source_constant_arguments);
LOG_OR_DUMP(
this,
5,
"Joining with model for `{}`: {}",
show(override),
override_model);
model.join_with(override_model);
}
callsite_model_cache_.emplace(CacheKey{call_target, position}, model);
return model;
}