service/method-inliner/CallSiteSummaries.h (80 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. */ #pragma once #include "Shrinker.h" using CallSiteArguments = constant_propagation::interprocedural::ArgumentDomain; struct CallSiteSummary { CallSiteArguments arguments; bool result_used; /* * The key of a call-site-summary is a canonical string representation of the * constant arguments. Usually, the string is quite small, it only rarely * contains fields or methods. */ std::string get_key() const; static void append_key_value(std::ostringstream& oss, const ConstantValue& value); }; struct CalleeCallSiteSummary { const DexMethod* method; const CallSiteSummary* call_site_summary; }; inline size_t hash_value(CalleeCallSiteSummary ccss) { return ((size_t)ccss.method) ^ (size_t)(ccss.call_site_summary); } inline bool operator==(const CalleeCallSiteSummary& a, const CalleeCallSiteSummary& b) { return a.method == b.method && a.call_site_summary == b.call_site_summary; } using InvokeCallSiteSummaries = std::vector<std::pair<IRInstruction*, const CallSiteSummary*>>; struct InvokeCallSiteSummariesAndDeadBlocks { InvokeCallSiteSummaries invoke_call_site_summaries; size_t dead_blocks{0}; }; using CallSiteSummaryOccurrences = std::pair<const CallSiteSummary*, size_t>; using MethodToMethodOccurrences = std::unordered_map<const DexMethod*, std::unordered_map<DexMethod*, size_t>>; namespace inliner { using GetCalleeFunction = std::function<DexMethod*(DexMethod*, IRInstruction*)>; using HasCalleeOtherCallSitesPredicate = std::function<bool(DexMethod*)>; struct CallSiteSummaryStats { std::atomic<size_t> constant_invoke_callers_unreachable{0}; std::atomic<size_t> constant_invoke_callers_analyzed{0}; std::atomic<size_t> constant_invoke_callers_unreachable_blocks{0}; std::atomic<size_t> constant_invoke_callers_critical_path_length{0}; }; class CallSiteSummarizer { shrinker::Shrinker& m_shrinker; const MethodToMethodOccurrences& m_callee_caller; const MethodToMethodOccurrences& m_caller_callee; GetCalleeFunction m_get_callee_fn; HasCalleeOtherCallSitesPredicate m_has_callee_other_call_sites_fn; std::function<bool(const ConstantValue&)>* m_filter_fn; CallSiteSummaryStats* m_stats; /** * For all (reachable) invoked methods, list of call-site summaries */ std::unordered_map<const DexMethod*, std::vector<CallSiteSummaryOccurrences>> m_callee_call_site_summary_occurrences; /** * For all (reachable) invoked methods, list of vinoke instructions */ std::unordered_map<const DexMethod*, std::vector<const IRInstruction*>> m_callee_call_site_invokes; /** * For all (reachable) invoke instructions, constant arguments */ ConcurrentMap<const IRInstruction*, const CallSiteSummary*> m_invoke_call_site_summaries; /** * Internalized call-site summaries. */ ConcurrentMap<std::string, std::unique_ptr<const CallSiteSummary>> m_call_site_summaries; /** * For all (reachable) invoke instructions in a given method, collect * information about their arguments, i.e. whether particular arguments * are constants. */ InvokeCallSiteSummariesAndDeadBlocks get_invoke_call_site_summaries( DexMethod* caller, const std::unordered_map<DexMethod*, size_t>& callees, const ConstantEnvironment& initial_env); public: CallSiteSummarizer( shrinker::Shrinker& shrinker, const MethodToMethodOccurrences& callee_caller, const MethodToMethodOccurrences& caller_callee, GetCalleeFunction get_callee_fn, HasCalleeOtherCallSitesPredicate has_callee_other_call_sites_fn, std::function<bool(const ConstantValue&)>* filter_fn, CallSiteSummaryStats* stats); void summarize(); const CallSiteSummary* internalize_call_site_summary( const CallSiteSummary& call_site_summary); const std::vector<CallSiteSummaryOccurrences>* get_callee_call_site_summary_occurrences(const DexMethod* callee) const; const std::vector<const IRInstruction*>* get_callee_call_site_invokes( const DexMethod* callee) const; const CallSiteSummary* get_instruction_call_site_summary( const IRInstruction* invoke_insn) const; }; } // namespace inliner