in source/LifecycleMethod.cpp [83:138]
void LifecycleMethod::create_methods(
const ClassHierarchies& class_hierarchies,
Methods& methods) const {
// All DexMethods created by `LifecycleMethod` have the same signature:
// void <method_name_>(<arguments>)
// The arguments are determined by the callees' arguments. This creates the
// map of argument type -> location/position (first argument is at index 1).
// The position corresponds to the register location containing the argument
// in the DexMethod's code. The register location will be used to create the
// invoke operation for methods that take a given DexType* as its argument.
TypeIndexMap type_index_map;
for (const auto& callee : callees_) {
const auto* type_list = callee.get_argument_types();
if (type_list == nullptr) {
ERROR(1, "Callee `{}` has invalid argument types.", callee.to_string());
continue;
}
for (auto* type : *type_list) {
type_index_map.emplace(type, type_index_map.size() + 1);
}
}
auto* MT_NULLABLE base_class_type = DexType::get_type(base_class_name_);
if (!base_class_type) {
WARNING(
1,
"Could not find type for base class name `{}`. Will skip creating life-cycle methods.",
base_class_name_);
return;
}
std::atomic<int> methods_created_count = 0;
const auto& children = class_hierarchies.extends(base_class_type);
LOG(3,
"Found {} child(ren) for type `{}`.",
children.size(),
base_class_name_);
auto queue = sparta::work_queue<DexType*>([&](DexType* child) {
const auto* method = create_dex_method(child, type_index_map);
if (method != nullptr) {
++methods_created_count;
methods.create(method);
}
});
for (const auto* child : children) {
queue.add_item(const_cast<DexType*>(child));
}
queue.run_all();
LOG(1,
"Created {} life-cycle methods for classes inheriting from `{}`",
methods_created_count,
base_class_name_);
}