xref: /aosp_15_r20/art/runtime/cha.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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_RUNTIME_CHA_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_CHA_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include <unordered_map>
21*795d594fSAndroid Build Coastguard Worker #include <unordered_set>
22*795d594fSAndroid Build Coastguard Worker 
23*795d594fSAndroid Build Coastguard Worker #include "base/locks.h"
24*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
25*795d594fSAndroid Build Coastguard Worker #include "base/pointer_size.h"
26*795d594fSAndroid Build Coastguard Worker #include "handle.h"
27*795d594fSAndroid Build Coastguard Worker #include "mirror/class.h"
28*795d594fSAndroid Build Coastguard Worker #include "oat/oat_quick_method_header.h"
29*795d594fSAndroid Build Coastguard Worker 
30*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
31*795d594fSAndroid Build Coastguard Worker 
32*795d594fSAndroid Build Coastguard Worker class ArtMethod;
33*795d594fSAndroid Build Coastguard Worker class LinearAlloc;
34*795d594fSAndroid Build Coastguard Worker 
35*795d594fSAndroid Build Coastguard Worker /**
36*795d594fSAndroid Build Coastguard Worker  * Class Hierarchy Analysis (CHA) tries to devirtualize virtual calls into
37*795d594fSAndroid Build Coastguard Worker  * direct calls based on the info generated by analyzing class hierarchies.
38*795d594fSAndroid Build Coastguard Worker  * If a class is not subclassed, or even if it's subclassed but one of its
39*795d594fSAndroid Build Coastguard Worker  * virtual methods isn't overridden, a virtual call for that method can be
40*795d594fSAndroid Build Coastguard Worker  * changed into a direct call.
41*795d594fSAndroid Build Coastguard Worker  *
42*795d594fSAndroid Build Coastguard Worker  * Each virtual method carries a single-implementation status. The status is
43*795d594fSAndroid Build Coastguard Worker  * incrementally maintained at the end of class linking time when method
44*795d594fSAndroid Build Coastguard Worker  * overriding takes effect.
45*795d594fSAndroid Build Coastguard Worker  *
46*795d594fSAndroid Build Coastguard Worker  * Compiler takes advantage of the single-implementation info of a
47*795d594fSAndroid Build Coastguard Worker  * method. If a method A has the single-implementation flag set, the compiler
48*795d594fSAndroid Build Coastguard Worker  * devirtualizes the virtual call for method A into a direct call, and
49*795d594fSAndroid Build Coastguard Worker  * further try to inline the direct call as a result. The compiler will
50*795d594fSAndroid Build Coastguard Worker  * also register a dependency that the compiled code depends on the
51*795d594fSAndroid Build Coastguard Worker  * assumption that method A has single-implementation status.
52*795d594fSAndroid Build Coastguard Worker  *
53*795d594fSAndroid Build Coastguard Worker  * When single-implementation info is updated at the end of class linking,
54*795d594fSAndroid Build Coastguard Worker  * and if method A's single-implementation status is invalidated, all compiled
55*795d594fSAndroid Build Coastguard Worker  * code that depends on the assumption that method A has single-implementation
56*795d594fSAndroid Build Coastguard Worker  * status need to be invalidated. Method entrypoints that have this dependency
57*795d594fSAndroid Build Coastguard Worker  * will be updated as a result. Method A can later be recompiled with less
58*795d594fSAndroid Build Coastguard Worker  * aggressive assumptions.
59*795d594fSAndroid Build Coastguard Worker  *
60*795d594fSAndroid Build Coastguard Worker  * For live compiled code that's on stack, deoptmization will be initiated
61*795d594fSAndroid Build Coastguard Worker  * to force the invalidated compiled code into interpreter mode to guarantee
62*795d594fSAndroid Build Coastguard Worker  * correctness. The deoptimization mechanism used is a hybrid of
63*795d594fSAndroid Build Coastguard Worker  * synchronous and asynchronous deoptimization. The synchronous deoptimization
64*795d594fSAndroid Build Coastguard Worker  * part checks a hidden local variable flag for the method, and if true,
65*795d594fSAndroid Build Coastguard Worker  * initiates deoptimization. The asynchronous deoptimization part issues a
66*795d594fSAndroid Build Coastguard Worker  * checkpoint that walks the stack and for any compiled code on the stack
67*795d594fSAndroid Build Coastguard Worker  * that should be deoptimized, set the hidden local variable value to be true.
68*795d594fSAndroid Build Coastguard Worker  *
69*795d594fSAndroid Build Coastguard Worker  * A cha_lock_ needs to be held for updating single-implementation status,
70*795d594fSAndroid Build Coastguard Worker  * and registering/unregistering CHA dependencies. Registering CHA dependency
71*795d594fSAndroid Build Coastguard Worker  * and making compiled code visible also need to be atomic. Otherwise, we
72*795d594fSAndroid Build Coastguard Worker  * may miss invalidating CHA dependents or making compiled code visible even
73*795d594fSAndroid Build Coastguard Worker  * after it is invalidated. Care needs to be taken between cha_lock_ and
74*795d594fSAndroid Build Coastguard Worker  * JitCodeCache::lock_ to guarantee the atomicity.
75*795d594fSAndroid Build Coastguard Worker  *
76*795d594fSAndroid Build Coastguard Worker  * We base our CHA on dynamically linked class profiles instead of doing static
77*795d594fSAndroid Build Coastguard Worker  * analysis. Static analysis can be too aggressive due to dynamic class loading
78*795d594fSAndroid Build Coastguard Worker  * at runtime, and too conservative since some classes may not be really loaded
79*795d594fSAndroid Build Coastguard Worker  * at runtime.
80*795d594fSAndroid Build Coastguard Worker  */
81*795d594fSAndroid Build Coastguard Worker class ClassHierarchyAnalysis {
82*795d594fSAndroid Build Coastguard Worker  public:
83*795d594fSAndroid Build Coastguard Worker   // Types for recording CHA dependencies.
84*795d594fSAndroid Build Coastguard Worker   // For invalidating CHA dependency, we need to know both the ArtMethod and
85*795d594fSAndroid Build Coastguard Worker   // the method header. If the ArtMethod has compiled code with the method header
86*795d594fSAndroid Build Coastguard Worker   // as the entrypoint, we update the entrypoint to the interpreter bridge.
87*795d594fSAndroid Build Coastguard Worker   // We will also deoptimize frames that are currently executing the code of
88*795d594fSAndroid Build Coastguard Worker   // the method header.
89*795d594fSAndroid Build Coastguard Worker   using MethodAndMethodHeaderPair = std::pair<ArtMethod*, OatQuickMethodHeader*>;
90*795d594fSAndroid Build Coastguard Worker   using ListOfDependentPairs = std::vector<MethodAndMethodHeaderPair>;
91*795d594fSAndroid Build Coastguard Worker 
ClassHierarchyAnalysis()92*795d594fSAndroid Build Coastguard Worker   ClassHierarchyAnalysis() {}
93*795d594fSAndroid Build Coastguard Worker 
94*795d594fSAndroid Build Coastguard Worker   // Add a dependency that compiled code with `dependent_header` for `dependent_method`
95*795d594fSAndroid Build Coastguard Worker   // assumes that virtual `method` has single-implementation.
96*795d594fSAndroid Build Coastguard Worker   void AddDependency(ArtMethod* method,
97*795d594fSAndroid Build Coastguard Worker                      ArtMethod* dependent_method,
98*795d594fSAndroid Build Coastguard Worker                      OatQuickMethodHeader* dependent_header) REQUIRES(Locks::cha_lock_);
99*795d594fSAndroid Build Coastguard Worker 
100*795d594fSAndroid Build Coastguard Worker   // Return compiled code that assumes that `method` has single-implementation.
101*795d594fSAndroid Build Coastguard Worker   const ListOfDependentPairs& GetDependents(ArtMethod* method) REQUIRES(Locks::cha_lock_);
102*795d594fSAndroid Build Coastguard Worker 
103*795d594fSAndroid Build Coastguard Worker   // Remove dependency tracking for compiled code that assumes that
104*795d594fSAndroid Build Coastguard Worker   // `method` has single-implementation.
105*795d594fSAndroid Build Coastguard Worker   void RemoveAllDependenciesFor(ArtMethod* method) REQUIRES(Locks::cha_lock_);
106*795d594fSAndroid Build Coastguard Worker 
107*795d594fSAndroid Build Coastguard Worker   // Remove from cha_dependency_map_ all entries that contain OatQuickMethodHeader from
108*795d594fSAndroid Build Coastguard Worker   // the given `method_headers` set.
109*795d594fSAndroid Build Coastguard Worker   // This is used when some compiled code is freed.
110*795d594fSAndroid Build Coastguard Worker   void RemoveDependentsWithMethodHeaders(
111*795d594fSAndroid Build Coastguard Worker       const std::unordered_set<OatQuickMethodHeader*>& method_headers)
112*795d594fSAndroid Build Coastguard Worker       REQUIRES(Locks::cha_lock_);
113*795d594fSAndroid Build Coastguard Worker 
114*795d594fSAndroid Build Coastguard Worker   // If a given class belongs to a linear allocation that is about to be deleted, in all its
115*795d594fSAndroid Build Coastguard Worker   // superclasses and superinterfaces reset SingleImplementation fields of their methods
116*795d594fSAndroid Build Coastguard Worker   // that might be affected by the deletion.
117*795d594fSAndroid Build Coastguard Worker   // The method is intended to be called during GC before ReclaimPhase, since it gets info from
118*795d594fSAndroid Build Coastguard Worker   // Java objects that are going to be collected.
119*795d594fSAndroid Build Coastguard Worker   // For the same reason it's important to access objects without read barrier to not revive them.
120*795d594fSAndroid Build Coastguard Worker   void ResetSingleImplementationInHierarchy(ObjPtr<mirror::Class> klass,
121*795d594fSAndroid Build Coastguard Worker                                             const LinearAlloc* alloc,
122*795d594fSAndroid Build Coastguard Worker                                             PointerSize pointer_size)
123*795d594fSAndroid Build Coastguard Worker       const REQUIRES_SHARED(Locks::mutator_lock_);
124*795d594fSAndroid Build Coastguard Worker 
125*795d594fSAndroid Build Coastguard Worker   // Update CHA info for methods that `klass` overrides, after loading `klass`.
126*795d594fSAndroid Build Coastguard Worker   void UpdateAfterLoadingOf(Handle<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
127*795d594fSAndroid Build Coastguard Worker 
128*795d594fSAndroid Build Coastguard Worker   // Remove all of the dependencies for a linear allocator. This is called when dex cache unloading
129*795d594fSAndroid Build Coastguard Worker   // occurs.
130*795d594fSAndroid Build Coastguard Worker   void RemoveDependenciesForLinearAlloc(Thread* self, const LinearAlloc* linear_alloc)
131*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Locks::cha_lock_);
132*795d594fSAndroid Build Coastguard Worker 
133*795d594fSAndroid Build Coastguard Worker  private:
134*795d594fSAndroid Build Coastguard Worker   void InitSingleImplementationFlag(Handle<mirror::Class> klass,
135*795d594fSAndroid Build Coastguard Worker                                     ArtMethod* method,
136*795d594fSAndroid Build Coastguard Worker                                     PointerSize pointer_size)
137*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
138*795d594fSAndroid Build Coastguard Worker 
139*795d594fSAndroid Build Coastguard Worker   // Check/update single-implementation info when one virtual method
140*795d594fSAndroid Build Coastguard Worker   // overrides another.
141*795d594fSAndroid Build Coastguard Worker   // `virtual_method` in `klass` overrides `method_in_super`.
142*795d594fSAndroid Build Coastguard Worker   // This may invalidate some assumptions on single-implementation.
143*795d594fSAndroid Build Coastguard Worker   // Append methods that should have their single-implementation flag invalidated
144*795d594fSAndroid Build Coastguard Worker   // to `invalidated_single_impl_methods`.
145*795d594fSAndroid Build Coastguard Worker   void CheckVirtualMethodSingleImplementationInfo(
146*795d594fSAndroid Build Coastguard Worker       Handle<mirror::Class> klass,
147*795d594fSAndroid Build Coastguard Worker       ArtMethod* virtual_method,
148*795d594fSAndroid Build Coastguard Worker       ArtMethod* method_in_super,
149*795d594fSAndroid Build Coastguard Worker       std::unordered_set<ArtMethod*>& invalidated_single_impl_methods,
150*795d594fSAndroid Build Coastguard Worker       PointerSize pointer_size)
151*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
152*795d594fSAndroid Build Coastguard Worker 
153*795d594fSAndroid Build Coastguard Worker   // Check/update single-implementation info when one method
154*795d594fSAndroid Build Coastguard Worker   // implements an interface method.
155*795d594fSAndroid Build Coastguard Worker   // `implementation_method` in `klass` implements `interface_method`.
156*795d594fSAndroid Build Coastguard Worker   // Append `interface_method` to `invalidated_single_impl_methods`
157*795d594fSAndroid Build Coastguard Worker   // if `interface_method` gets a new implementation.
158*795d594fSAndroid Build Coastguard Worker   void CheckInterfaceMethodSingleImplementationInfo(
159*795d594fSAndroid Build Coastguard Worker       Handle<mirror::Class> klass,
160*795d594fSAndroid Build Coastguard Worker       ArtMethod* interface_method,
161*795d594fSAndroid Build Coastguard Worker       ArtMethod* implementation_method,
162*795d594fSAndroid Build Coastguard Worker       std::unordered_set<ArtMethod*>& invalidated_single_impl_methods,
163*795d594fSAndroid Build Coastguard Worker       PointerSize pointer_size)
164*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
165*795d594fSAndroid Build Coastguard Worker 
166*795d594fSAndroid Build Coastguard Worker   void InvalidateSingleImplementationMethods(
167*795d594fSAndroid Build Coastguard Worker       std::unordered_set<ArtMethod*>& invalidated_single_impl_methods)
168*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
169*795d594fSAndroid Build Coastguard Worker 
170*795d594fSAndroid Build Coastguard Worker   // A map that maps a method to a set of compiled code that assumes that method has a
171*795d594fSAndroid Build Coastguard Worker   // single implementation, which is used to do CHA-based devirtualization.
172*795d594fSAndroid Build Coastguard Worker   std::unordered_map<ArtMethod*, ListOfDependentPairs> cha_dependency_map_
173*795d594fSAndroid Build Coastguard Worker     GUARDED_BY(Locks::cha_lock_);
174*795d594fSAndroid Build Coastguard Worker 
175*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(ClassHierarchyAnalysis);
176*795d594fSAndroid Build Coastguard Worker };
177*795d594fSAndroid Build Coastguard Worker 
178*795d594fSAndroid Build Coastguard Worker }  // namespace art
179*795d594fSAndroid Build Coastguard Worker 
180*795d594fSAndroid Build Coastguard Worker #endif  // ART_RUNTIME_CHA_H_
181