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