1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_COMPILER_OPTIMIZING_ESCAPE_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_OPTIMIZING_ESCAPE_H_
19*795d594fSAndroid Build Coastguard Worker
20*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
21*795d594fSAndroid Build Coastguard Worker
22*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
23*795d594fSAndroid Build Coastguard Worker
24*795d594fSAndroid Build Coastguard Worker class HInstruction;
25*795d594fSAndroid Build Coastguard Worker
26*795d594fSAndroid Build Coastguard Worker /*
27*795d594fSAndroid Build Coastguard Worker * Methods related to escape analysis, i.e. determining whether an object
28*795d594fSAndroid Build Coastguard Worker * allocation is visible outside ('escapes') its immediate method context.
29*795d594fSAndroid Build Coastguard Worker */
30*795d594fSAndroid Build Coastguard Worker
31*795d594fSAndroid Build Coastguard Worker // A visitor for seeing all instructions escape analysis considers escaping.
32*795d594fSAndroid Build Coastguard Worker // Called with each user of the reference passed to 'VisitEscapes'. Return true
33*795d594fSAndroid Build Coastguard Worker // to continue iteration and false to stop.
34*795d594fSAndroid Build Coastguard Worker class EscapeVisitor {
35*795d594fSAndroid Build Coastguard Worker public:
~EscapeVisitor()36*795d594fSAndroid Build Coastguard Worker virtual ~EscapeVisitor() {}
37*795d594fSAndroid Build Coastguard Worker virtual bool Visit(HInstruction* escape) = 0;
operator()38*795d594fSAndroid Build Coastguard Worker bool operator()(HInstruction* user) {
39*795d594fSAndroid Build Coastguard Worker return Visit(user);
40*795d594fSAndroid Build Coastguard Worker }
41*795d594fSAndroid Build Coastguard Worker };
42*795d594fSAndroid Build Coastguard Worker
43*795d594fSAndroid Build Coastguard Worker // An explicit EscapeVisitor for lambdas
44*795d594fSAndroid Build Coastguard Worker template <typename F>
45*795d594fSAndroid Build Coastguard Worker class LambdaEscapeVisitor final : public EscapeVisitor {
46*795d594fSAndroid Build Coastguard Worker public:
LambdaEscapeVisitor(F f)47*795d594fSAndroid Build Coastguard Worker explicit LambdaEscapeVisitor(F f) : func_(f) {}
Visit(HInstruction * escape)48*795d594fSAndroid Build Coastguard Worker bool Visit(HInstruction* escape) override {
49*795d594fSAndroid Build Coastguard Worker return func_(escape);
50*795d594fSAndroid Build Coastguard Worker }
51*795d594fSAndroid Build Coastguard Worker
52*795d594fSAndroid Build Coastguard Worker private:
53*795d594fSAndroid Build Coastguard Worker F func_;
54*795d594fSAndroid Build Coastguard Worker };
55*795d594fSAndroid Build Coastguard Worker
56*795d594fSAndroid Build Coastguard Worker // This functor is used with the escape-checking functions. If the NoEscape
57*795d594fSAndroid Build Coastguard Worker // function returns true escape analysis will consider 'user' to not have
58*795d594fSAndroid Build Coastguard Worker // escaped 'reference'. This allows clients with additional information to
59*795d594fSAndroid Build Coastguard Worker // supplement the escape-analysis. If the NoEscape function returns false then
60*795d594fSAndroid Build Coastguard Worker // the normal escape-checking code will be used to determine whether or not
61*795d594fSAndroid Build Coastguard Worker // 'reference' escapes.
62*795d594fSAndroid Build Coastguard Worker class NoEscapeCheck {
63*795d594fSAndroid Build Coastguard Worker public:
~NoEscapeCheck()64*795d594fSAndroid Build Coastguard Worker virtual ~NoEscapeCheck() {}
65*795d594fSAndroid Build Coastguard Worker virtual bool NoEscape(HInstruction* reference, HInstruction* user) = 0;
operator()66*795d594fSAndroid Build Coastguard Worker bool operator()(HInstruction* ref, HInstruction* user) {
67*795d594fSAndroid Build Coastguard Worker return NoEscape(ref, user);
68*795d594fSAndroid Build Coastguard Worker }
69*795d594fSAndroid Build Coastguard Worker };
70*795d594fSAndroid Build Coastguard Worker
71*795d594fSAndroid Build Coastguard Worker // An explicit NoEscapeCheck for use with c++ lambdas.
72*795d594fSAndroid Build Coastguard Worker template <typename F>
73*795d594fSAndroid Build Coastguard Worker class LambdaNoEscapeCheck final : public NoEscapeCheck {
74*795d594fSAndroid Build Coastguard Worker public:
LambdaNoEscapeCheck(F f)75*795d594fSAndroid Build Coastguard Worker explicit LambdaNoEscapeCheck(F f) : func_(f) {}
NoEscape(HInstruction * ref,HInstruction * user)76*795d594fSAndroid Build Coastguard Worker bool NoEscape(HInstruction* ref, HInstruction* user) override {
77*795d594fSAndroid Build Coastguard Worker return func_(ref, user);
78*795d594fSAndroid Build Coastguard Worker }
79*795d594fSAndroid Build Coastguard Worker
80*795d594fSAndroid Build Coastguard Worker private:
81*795d594fSAndroid Build Coastguard Worker F func_;
82*795d594fSAndroid Build Coastguard Worker };
83*795d594fSAndroid Build Coastguard Worker
84*795d594fSAndroid Build Coastguard Worker /*
85*795d594fSAndroid Build Coastguard Worker * Performs escape analysis on the given instruction, typically a reference to an
86*795d594fSAndroid Build Coastguard Worker * allocation. The method assigns true to parameter 'is_singleton' if the reference
87*795d594fSAndroid Build Coastguard Worker * is the only name that can refer to its value during the lifetime of the method,
88*795d594fSAndroid Build Coastguard Worker * meaning that the reference is not aliased with something else, is not stored to
89*795d594fSAndroid Build Coastguard Worker * heap memory, and not passed to another method. In addition, the method assigns
90*795d594fSAndroid Build Coastguard Worker * true to parameter 'is_singleton_and_not_returned' if the reference is a singleton
91*795d594fSAndroid Build Coastguard Worker * and not returned to the caller and to parameter 'is_singleton_and_not_deopt_visible'
92*795d594fSAndroid Build Coastguard Worker * if the reference is a singleton and not used as an environment local of an
93*795d594fSAndroid Build Coastguard Worker * HDeoptimize instruction (clients of the final value must run after BCE to ensure
94*795d594fSAndroid Build Coastguard Worker * all such instructions have been introduced already).
95*795d594fSAndroid Build Coastguard Worker *
96*795d594fSAndroid Build Coastguard Worker * Note that being visible to a HDeoptimize instruction does not count for ordinary
97*795d594fSAndroid Build Coastguard Worker * escape analysis, since switching between compiled code and interpreted code keeps
98*795d594fSAndroid Build Coastguard Worker * non escaping references restricted to the lifetime of the method and the thread
99*795d594fSAndroid Build Coastguard Worker * executing it. This property only concerns optimizations that are interested in
100*795d594fSAndroid Build Coastguard Worker * escape analysis with respect to the *compiled* code (such as LSE).
101*795d594fSAndroid Build Coastguard Worker *
102*795d594fSAndroid Build Coastguard Worker * When set, the no_escape function is applied to any use of the allocation instruction
103*795d594fSAndroid Build Coastguard Worker * prior to any built-in escape analysis. This allows clients to define better escape
104*795d594fSAndroid Build Coastguard Worker * analysis in certain case-specific circumstances. If 'no_escape(reference, user)'
105*795d594fSAndroid Build Coastguard Worker * returns true, the user is assumed *not* to cause any escape right away. The return
106*795d594fSAndroid Build Coastguard Worker * value false means the client cannot provide a definite answer and built-in escape
107*795d594fSAndroid Build Coastguard Worker * analysis is applied to the user instead.
108*795d594fSAndroid Build Coastguard Worker */
109*795d594fSAndroid Build Coastguard Worker void CalculateEscape(HInstruction* reference,
110*795d594fSAndroid Build Coastguard Worker NoEscapeCheck& no_escape,
111*795d594fSAndroid Build Coastguard Worker /*out*/ bool* is_singleton,
112*795d594fSAndroid Build Coastguard Worker /*out*/ bool* is_singleton_and_not_returned,
113*795d594fSAndroid Build Coastguard Worker /*out*/ bool* is_singleton_and_not_deopt_visible);
114*795d594fSAndroid Build Coastguard Worker
CalculateEscape(HInstruction * reference,bool (* no_escape_fn)(HInstruction *,HInstruction *),bool * is_singleton,bool * is_singleton_and_not_returned,bool * is_singleton_and_not_deopt_visible)115*795d594fSAndroid Build Coastguard Worker inline void CalculateEscape(HInstruction* reference,
116*795d594fSAndroid Build Coastguard Worker bool (*no_escape_fn)(HInstruction*, HInstruction*),
117*795d594fSAndroid Build Coastguard Worker /*out*/ bool* is_singleton,
118*795d594fSAndroid Build Coastguard Worker /*out*/ bool* is_singleton_and_not_returned,
119*795d594fSAndroid Build Coastguard Worker /*out*/ bool* is_singleton_and_not_deopt_visible) {
120*795d594fSAndroid Build Coastguard Worker LambdaNoEscapeCheck esc(no_escape_fn);
121*795d594fSAndroid Build Coastguard Worker LambdaNoEscapeCheck noop_esc([](HInstruction*, HInstruction*) { return false; });
122*795d594fSAndroid Build Coastguard Worker CalculateEscape(reference,
123*795d594fSAndroid Build Coastguard Worker no_escape_fn == nullptr ? static_cast<NoEscapeCheck&>(noop_esc) : esc,
124*795d594fSAndroid Build Coastguard Worker is_singleton,
125*795d594fSAndroid Build Coastguard Worker is_singleton_and_not_returned,
126*795d594fSAndroid Build Coastguard Worker is_singleton_and_not_deopt_visible);
127*795d594fSAndroid Build Coastguard Worker }
128*795d594fSAndroid Build Coastguard Worker
129*795d594fSAndroid Build Coastguard Worker /*
130*795d594fSAndroid Build Coastguard Worker * Performs escape analysis and visits each escape of the reference. Does not try to calculate any
131*795d594fSAndroid Build Coastguard Worker * overall information about the method. Escapes are calculated in the same way as CalculateEscape.
132*795d594fSAndroid Build Coastguard Worker *
133*795d594fSAndroid Build Coastguard Worker * The escape_visitor should return true to continue visiting, false otherwise.
134*795d594fSAndroid Build Coastguard Worker */
135*795d594fSAndroid Build Coastguard Worker void VisitEscapes(HInstruction* reference, EscapeVisitor& escape_visitor);
136*795d594fSAndroid Build Coastguard Worker
137*795d594fSAndroid Build Coastguard Worker /*
138*795d594fSAndroid Build Coastguard Worker * Convenience method for testing the singleton and not returned properties at once.
139*795d594fSAndroid Build Coastguard Worker * Callers should be aware that this method invokes the full analysis at each call.
140*795d594fSAndroid Build Coastguard Worker */
141*795d594fSAndroid Build Coastguard Worker bool DoesNotEscape(HInstruction* reference, NoEscapeCheck& no_escape);
142*795d594fSAndroid Build Coastguard Worker
DoesNotEscape(HInstruction * reference,bool (* no_escape_fn)(HInstruction *,HInstruction *))143*795d594fSAndroid Build Coastguard Worker inline bool DoesNotEscape(HInstruction* reference,
144*795d594fSAndroid Build Coastguard Worker bool (*no_escape_fn)(HInstruction*, HInstruction*)) {
145*795d594fSAndroid Build Coastguard Worker LambdaNoEscapeCheck<typeof(no_escape_fn)> esc(no_escape_fn);
146*795d594fSAndroid Build Coastguard Worker return DoesNotEscape(reference, esc);
147*795d594fSAndroid Build Coastguard Worker }
148*795d594fSAndroid Build Coastguard Worker
149*795d594fSAndroid Build Coastguard Worker } // namespace art
150*795d594fSAndroid Build Coastguard Worker
151*795d594fSAndroid Build Coastguard Worker #endif // ART_COMPILER_OPTIMIZING_ESCAPE_H_
152