diff options
author | 2020-09-23 15:04:36 -0700 | |
---|---|---|
committer | 2020-09-25 04:46:32 +0000 | |
commit | 5ba66998281af9719e5d5ef84fd095181d4cf9a8 (patch) | |
tree | 96d6b307af969eade69f390a1af3ab623523b8a1 /compiler/optimizing/escape.h | |
parent | 6076b6959ac6dd2f5f6c93d119b37899f70a30a8 (diff) |
Refactor Escape-analysis to use visitors
The current escape-analysis is entirely built around finding a single
'does-escape' boolean (and a few ancillary booleans). This change adds
a new VisitEscapes function that allows one to more easily track which
instructions cause escapes and rewrites the other escape-analysis
functions in terms of this VisitEscapes function.
Test: ./test.py --host
Bug: 67037140
Change-Id: Ie5ad7580544be21713d040c2943cae19ff5414d4
Diffstat (limited to 'compiler/optimizing/escape.h')
-rw-r--r-- | compiler/optimizing/escape.h | 85 |
1 files changed, 83 insertions, 2 deletions
diff --git a/compiler/optimizing/escape.h b/compiler/optimizing/escape.h index 75e37b0551..5402cb1763 100644 --- a/compiler/optimizing/escape.h +++ b/compiler/optimizing/escape.h @@ -26,6 +26,59 @@ class HInstruction; * allocation is visible outside ('escapes') its immediate method context. */ +// A visitor for seeing all instructions escape analysis considers escaping. +// Called with each user of the reference passed to 'VisitEscapes'. Return true +// to continue iteration and false to stop. +class EscapeVisitor { + public: + virtual ~EscapeVisitor() {} + virtual bool Visit(HInstruction* escape) = 0; + bool operator()(HInstruction* user) { + return Visit(user); + } +}; + +// An explicit EscapeVisitor for lambdas +template <typename F> +class LambdaEscapeVisitor final : public EscapeVisitor { + public: + explicit LambdaEscapeVisitor(F f) : func_(f) {} + bool Visit(HInstruction* escape) override { + return func_(escape); + } + + private: + F func_; +}; + +// This functor is used with the escape-checking functions. If the NoEscape +// function returns true escape analysis will consider 'user' to not have +// escaped 'reference'. This allows clients with additional information to +// supplement the escape-analysis. If the NoEscape function returns false then +// the normal escape-checking code will be used to determine whether or not +// 'reference' escapes. +class NoEscapeCheck { + public: + virtual ~NoEscapeCheck() {} + virtual bool NoEscape(HInstruction* reference, HInstruction* user) = 0; + bool operator()(HInstruction* ref, HInstruction* user) { + return NoEscape(ref, user); + } +}; + +// An explicit NoEscapeCheck for use with c++ lambdas. +template <typename F> +class LambdaNoEscapeCheck final : public NoEscapeCheck { + public: + explicit LambdaNoEscapeCheck(F f) : func_(f) {} + bool NoEscape(HInstruction* ref, HInstruction* user) override { + return func_(ref, user); + } + + private: + F func_; +}; + /* * Performs escape analysis on the given instruction, typically a reference to an * allocation. The method assigns true to parameter 'is_singleton' if the reference @@ -52,16 +105,44 @@ class HInstruction; * analysis is applied to the user instead. */ void CalculateEscape(HInstruction* reference, - bool (*no_escape)(HInstruction*, HInstruction*), + NoEscapeCheck& no_escape, /*out*/ bool* is_singleton, /*out*/ bool* is_singleton_and_not_returned, /*out*/ bool* is_singleton_and_not_deopt_visible); +inline void CalculateEscape(HInstruction* reference, + bool (*no_escape_fn)(HInstruction*, HInstruction*), + /*out*/ bool* is_singleton, + /*out*/ bool* is_singleton_and_not_returned, + /*out*/ bool* is_singleton_and_not_deopt_visible) { + LambdaNoEscapeCheck esc(no_escape_fn); + LambdaNoEscapeCheck noop_esc([](HInstruction*, HInstruction*) { return false; }); + CalculateEscape(reference, + no_escape_fn == nullptr ? static_cast<NoEscapeCheck&>(noop_esc) : esc, + is_singleton, + is_singleton_and_not_returned, + is_singleton_and_not_deopt_visible); +} + +/* + * Performs escape analysis and visits each escape of the reference. Does not try to calculate any + * overall information about the method. Escapes are calculated in the same way as CalculateEscape. + * + * The escape_visitor should return true to continue visiting, false otherwise. + */ +void VisitEscapes(HInstruction* reference, EscapeVisitor& escape_visitor); + /* * Convenience method for testing the singleton and not returned properties at once. * Callers should be aware that this method invokes the full analysis at each call. */ -bool DoesNotEscape(HInstruction* reference, bool (*no_escape)(HInstruction*, HInstruction*)); +bool DoesNotEscape(HInstruction* reference, NoEscapeCheck& no_escape); + +inline bool DoesNotEscape(HInstruction* reference, + bool (*no_escape_fn)(HInstruction*, HInstruction*)) { + LambdaNoEscapeCheck<typeof(no_escape_fn)> esc(no_escape_fn); + return DoesNotEscape(reference, esc); +} } // namespace art |