File: escape.h

package info (click to toggle)
android-platform-art 14.0.0%2Br15-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 96,796 kB
  • sloc: cpp: 522,217; java: 194,312; asm: 28,950; python: 14,910; xml: 5,087; sh: 4,528; ansic: 4,035; makefile: 110; perl: 77
file content (151 lines) | stat: -rw-r--r-- 6,169 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_COMPILER_OPTIMIZING_ESCAPE_H_
#define ART_COMPILER_OPTIMIZING_ESCAPE_H_

#include "base/macros.h"

namespace art HIDDEN {

class HInstruction;

/*
 * Methods related to escape analysis, i.e. determining whether an object
 * 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
 * is the only name that can refer to its value during the lifetime of the method,
 * meaning that the reference is not aliased with something else, is not stored to
 * heap memory, and not passed to another method. In addition, the method assigns
 * true to parameter 'is_singleton_and_not_returned' if the reference is a singleton
 * and not returned to the caller and to parameter 'is_singleton_and_not_deopt_visible'
 * if the reference is a singleton and not used as an environment local of an
 * HDeoptimize instruction (clients of the final value must run after BCE to ensure
 * all such instructions have been introduced already).
 *
 * Note that being visible to a HDeoptimize instruction does not count for ordinary
 * escape analysis, since switching between compiled code and interpreted code keeps
 * non escaping references restricted to the lifetime of the method and the thread
 * executing it. This property only concerns optimizations that are interested in
 * escape analysis with respect to the *compiled* code (such as LSE).
 *
 * When set, the no_escape function is applied to any use of the allocation instruction
 * prior to any built-in escape analysis. This allows clients to define better escape
 * analysis in certain case-specific circumstances. If 'no_escape(reference, user)'
 * returns true, the user is assumed *not* to cause any escape right away. The return
 * value false means the client cannot provide a definite answer and built-in escape
 * analysis is applied to the user instead.
 */
void CalculateEscape(HInstruction* reference,
                     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, 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

#endif  // ART_COMPILER_OPTIMIZING_ESCAPE_H_