opt/virtual_merging/VirtualMerging.cpp
// Part 3: For each virtual scope, identify all pairs of methods where
//         one can be merged with another. The list of pairs is ordered in
//         way that it can be later processed sequentially.
Part 3: For each virtual scope, identify all pairs of methods where
one can be merged with another. The list of pairs is ordered in
way that it can be later processed sequentially.
Part 3 : For each virtual scope identify all pairs of methods where one can be merged with another . The list of pairs is ordered in way that it can be later processed sequentially .
VirtualMerging::MergablePairsByVirtualScope
VirtualMerging::compute_mergeable_pairs_by_virtual_scopes(
    const method_profiles::MethodProfiles& profiles,
    VirtualMergingStats& stats) const {
  ConcurrentMap<const VirtualScope*, LocalStats> local_stats;
  std::vector<const VirtualScope*> virtual_scopes;
  for (auto& p : m_mergeable_scope_methods) {
    virtual_scopes.push_back(p.first);
  }
  ConcurrentMap<const VirtualScope*,
                std::vector<std::pair<const DexMethod*, const DexMethod*>>>
      mergeable_pairs_by_virtual_scopes;
  walk::parallel::virtual_scopes(
      virtual_scopes, [&](const VirtualScope* virtual_scope) {
        MergePairsBuilder mpb(virtual_scope);
        auto res = mpb.build(m_mergeable_scope_methods.at(virtual_scope),
                             m_xstores, m_xdexes, profiles);
        if (!res) {
          return;
        }
        local_stats.emplace(virtual_scope, res->first);
        if (!res->second.empty()) {
          mergeable_pairs_by_virtual_scopes.emplace(virtual_scope,
                                                    std::move(res->second));
        }
      });
  stats.virtual_scopes_with_mergeable_pairs +=
      mergeable_pairs_by_virtual_scopes.size();
  size_t overriding_methods = 0;
  for (auto& p : local_stats) {
    overriding_methods += p.second.overriding_methods;
    stats.cross_store_refs += p.second.cross_store_refs;
    stats.cross_dex_refs += p.second.cross_dex_refs;
    stats.inconcrete_overridden_methods +=
        p.second.inconcrete_overridden_methods;
  }
  always_assert(overriding_methods <= stats.mergeable_virtual_methods);
  stats.annotated_methods =
      stats.mergeable_virtual_methods - overriding_methods;
  MergablePairsByVirtualScope out;
  for (auto& p : mergeable_pairs_by_virtual_scopes) {
    const auto& mergeable_pairs = p.second;
    stats.mergeable_pairs += mergeable_pairs.size();
    out.insert(p);
  }
  always_assert(mergeable_pairs_by_virtual_scopes.size() == out.size());
  always_assert(stats.mergeable_pairs ==
                stats.mergeable_virtual_methods - stats.annotated_methods -
                    stats.cross_store_refs - stats.cross_dex_refs -
                    stats.inconcrete_overridden_methods);
  return out;
}
VirtualMerging :: MergablePairsByVirtualScope VirtualMerging :: compute_mergeable_pairs_by_virtual_scopes ( const method_profiles :: MethodProfiles & profiles , VirtualMergingStats & stats ) const { ConcurrentMap < const VirtualScope * , LocalStats > local_stats ; std :: vector < const VirtualScope * > virtual_scopes ; for ( auto & p : m_mergeable_scope_methods ) { virtual_scopes . push_back ( p . first ) ; } ConcurrentMap < const VirtualScope * , std :: vector < std :: pair < const DexMethod * , const DexMethod * > > > mergeable_pairs_by_virtual_scopes ; walk :: parallel :: virtual_scopes ( virtual_scopes , [ & ] ( const VirtualScope * virtual_scope ) { MergePairsBuilder mpb ( virtual_scope ) ; auto res = mpb . build ( m_mergeable_scope_methods . at ( virtual_scope ) , m_xstores , m_xdexes , profiles ) ; if ( ! res ) { return ; } local_stats . emplace ( virtual_scope , res -> first ) ; if ( ! res -> second . empty ( ) ) { mergeable_pairs_by_virtual_scopes . emplace ( virtual_scope , std :: move ( res -> second ) ) ; } } ) ; stats . virtual_scopes_with_mergeable_pairs += mergeable_pairs_by_virtual_scopes . size ( ) ; size_t overriding_methods = 0 ; for ( auto & p : local_stats ) { overriding_methods += p . second . overriding_methods ; stats . cross_store_refs += p . second . cross_store_refs ; stats . cross_dex_refs += p . second . cross_dex_refs ; stats . inconcrete_overridden_methods += p . second . inconcrete_overridden_methods ; } always_assert ( overriding_methods <= stats . mergeable_virtual_methods ) ; stats . annotated_methods = stats . mergeable_virtual_methods - overriding_methods ; MergablePairsByVirtualScope out ; for ( auto & p : mergeable_pairs_by_virtual_scopes ) { const auto & mergeable_pairs = p . second ; stats . mergeable_pairs += mergeable_pairs . size ( ) ; out . insert ( p ) ; } always_assert ( mergeable_pairs_by_virtual_scopes . size ( ) == out . size ( ) ) ; always_assert ( stats . mergeable_pairs == stats . mergeable_virtual_methods - stats . annotated_methods - stats . cross_store_refs - stats . cross_dex_refs - stats . inconcrete_overridden_methods ) ; return out ; }
Part 3: For each virtual scope, identify all pairs of methods where
one can be merged with another.
Part 3 : For each virtual scope identify all pairs of methods where one can be merged with another .