source/Overrides.cpp (75 lines of code) (raw):
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <memory>
#include <vector>
#include <MethodOverrideGraph.h>
#include <Show.h>
#include <Walkers.h>
#include <mariana-trench/Assert.h>
#include <mariana-trench/JsonValidation.h>
#include <mariana-trench/Log.h>
#include <mariana-trench/Methods.h>
#include <mariana-trench/Overrides.h>
namespace marianatrench {
Overrides::Overrides(
const Options& options,
const Methods& method_factory,
const DexStoresVector& stores) {
// Compute overrides.
std::vector<std::unique_ptr<const method_override_graph::Graph>>
method_override_graphs;
for (const auto& scope : DexStoreClassesIterator(stores)) {
method_override_graphs.push_back(method_override_graph::build_graph(scope));
}
// Record overrides.
for (const auto& scope : DexStoreClassesIterator(stores)) {
walk::parallel::methods(scope, [&](const DexMethod* dex_method) {
std::unordered_set<const Method*> method_overrides;
for (const auto& graph : method_override_graphs) {
auto overrides_in_scope = method_override_graph::get_overriding_methods(
*graph, dex_method, /* include_interfaces */ true);
for (const auto* override : overrides_in_scope) {
method_overrides.insert(method_factory.get(override));
}
}
set(method_factory.get(dex_method), std::move(method_overrides));
});
}
if (options.dump_overrides()) {
auto overrides_path = options.overrides_output_path();
LOG(1, "Writing override graph to `{}`", overrides_path.native());
JsonValidation::write_json_file(overrides_path, to_json());
}
}
const std::unordered_set<const Method*>& Overrides::get(
const Method* method) const {
auto* overrides = overrides_.get(method, /* default */ nullptr);
if (overrides != nullptr) {
return *overrides;
} else {
return empty_method_set_;
}
}
void Overrides::set(
const Method* method,
std::unordered_set<const Method*> overrides) {
if (overrides.empty()) {
mt_assert(overrides_.get(method, /* default */ nullptr) == nullptr);
return;
}
overrides_.emplace(
method,
std::make_unique<std::unordered_set<const Method*>>(
std::move(overrides)));
}
const std::unordered_set<const Method*>& Overrides::empty_method_set() const {
return empty_method_set_;
}
Json::Value Overrides::to_json() const {
auto value = Json::Value(Json::objectValue);
for (auto [method, overrides] : overrides_) {
auto overrides_value = Json::Value(Json::arrayValue);
for (const auto* override : *overrides) {
overrides_value.append(Json::Value(show(override)));
}
value[method->show()] = overrides_value;
}
return value;
}
} // namespace marianatrench