xref: /aosp_15_r20/art/runtime/cha.cc (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 #include "cha.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include "art_method-inl.h"
20*795d594fSAndroid Build Coastguard Worker #include "base/logging.h"  // For VLOG
21*795d594fSAndroid Build Coastguard Worker #include "base/mutex.h"
22*795d594fSAndroid Build Coastguard Worker #include "jit/jit.h"
23*795d594fSAndroid Build Coastguard Worker #include "jit/jit_code_cache.h"
24*795d594fSAndroid Build Coastguard Worker #include "linear_alloc.h"
25*795d594fSAndroid Build Coastguard Worker #include "mirror/class_loader.h"
26*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
27*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
28*795d594fSAndroid Build Coastguard Worker #include "stack.h"
29*795d594fSAndroid Build Coastguard Worker #include "thread.h"
30*795d594fSAndroid Build Coastguard Worker #include "thread_list.h"
31*795d594fSAndroid Build Coastguard Worker #include "thread_pool.h"
32*795d594fSAndroid Build Coastguard Worker 
33*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
34*795d594fSAndroid Build Coastguard Worker 
AddDependency(ArtMethod * method,ArtMethod * dependent_method,OatQuickMethodHeader * dependent_header)35*795d594fSAndroid Build Coastguard Worker void ClassHierarchyAnalysis::AddDependency(ArtMethod* method,
36*795d594fSAndroid Build Coastguard Worker                                            ArtMethod* dependent_method,
37*795d594fSAndroid Build Coastguard Worker                                            OatQuickMethodHeader* dependent_header) {
38*795d594fSAndroid Build Coastguard Worker   const auto it = cha_dependency_map_.insert(
39*795d594fSAndroid Build Coastguard Worker       decltype(cha_dependency_map_)::value_type(method, ListOfDependentPairs())).first;
40*795d594fSAndroid Build Coastguard Worker   it->second.push_back({dependent_method, dependent_header});
41*795d594fSAndroid Build Coastguard Worker }
42*795d594fSAndroid Build Coastguard Worker 
43*795d594fSAndroid Build Coastguard Worker static const ClassHierarchyAnalysis::ListOfDependentPairs s_empty_vector;
44*795d594fSAndroid Build Coastguard Worker 
GetDependents(ArtMethod * method)45*795d594fSAndroid Build Coastguard Worker const ClassHierarchyAnalysis::ListOfDependentPairs& ClassHierarchyAnalysis::GetDependents(
46*795d594fSAndroid Build Coastguard Worker     ArtMethod* method) {
47*795d594fSAndroid Build Coastguard Worker   auto it = cha_dependency_map_.find(method);
48*795d594fSAndroid Build Coastguard Worker   if (it != cha_dependency_map_.end()) {
49*795d594fSAndroid Build Coastguard Worker     return it->second;
50*795d594fSAndroid Build Coastguard Worker   }
51*795d594fSAndroid Build Coastguard Worker   return s_empty_vector;
52*795d594fSAndroid Build Coastguard Worker }
53*795d594fSAndroid Build Coastguard Worker 
RemoveAllDependenciesFor(ArtMethod * method)54*795d594fSAndroid Build Coastguard Worker void ClassHierarchyAnalysis::RemoveAllDependenciesFor(ArtMethod* method) {
55*795d594fSAndroid Build Coastguard Worker   cha_dependency_map_.erase(method);
56*795d594fSAndroid Build Coastguard Worker }
57*795d594fSAndroid Build Coastguard Worker 
RemoveDependentsWithMethodHeaders(const std::unordered_set<OatQuickMethodHeader * > & method_headers)58*795d594fSAndroid Build Coastguard Worker void ClassHierarchyAnalysis::RemoveDependentsWithMethodHeaders(
59*795d594fSAndroid Build Coastguard Worker     const std::unordered_set<OatQuickMethodHeader*>& method_headers) {
60*795d594fSAndroid Build Coastguard Worker   // Iterate through all entries in the dependency map and remove any entry that
61*795d594fSAndroid Build Coastguard Worker   // contains one of those in method_headers.
62*795d594fSAndroid Build Coastguard Worker   for (auto map_it = cha_dependency_map_.begin(); map_it != cha_dependency_map_.end(); ) {
63*795d594fSAndroid Build Coastguard Worker     ListOfDependentPairs& dependents = map_it->second;
64*795d594fSAndroid Build Coastguard Worker     dependents.erase(
65*795d594fSAndroid Build Coastguard Worker         std::remove_if(
66*795d594fSAndroid Build Coastguard Worker             dependents.begin(),
67*795d594fSAndroid Build Coastguard Worker             dependents.end(),
68*795d594fSAndroid Build Coastguard Worker             [&method_headers](MethodAndMethodHeaderPair& dependent) {
69*795d594fSAndroid Build Coastguard Worker               return method_headers.find(dependent.second) != method_headers.end();
70*795d594fSAndroid Build Coastguard Worker             }),
71*795d594fSAndroid Build Coastguard Worker         dependents.end());
72*795d594fSAndroid Build Coastguard Worker 
73*795d594fSAndroid Build Coastguard Worker     // Remove the map entry if there are no more dependents.
74*795d594fSAndroid Build Coastguard Worker     if (dependents.empty()) {
75*795d594fSAndroid Build Coastguard Worker       map_it = cha_dependency_map_.erase(map_it);
76*795d594fSAndroid Build Coastguard Worker     } else {
77*795d594fSAndroid Build Coastguard Worker       map_it++;
78*795d594fSAndroid Build Coastguard Worker     }
79*795d594fSAndroid Build Coastguard Worker   }
80*795d594fSAndroid Build Coastguard Worker }
81*795d594fSAndroid Build Coastguard Worker 
ResetSingleImplementationInHierarchy(ObjPtr<mirror::Class> klass,const LinearAlloc * alloc,const PointerSize pointer_size) const82*795d594fSAndroid Build Coastguard Worker void ClassHierarchyAnalysis::ResetSingleImplementationInHierarchy(ObjPtr<mirror::Class> klass,
83*795d594fSAndroid Build Coastguard Worker                                                                   const LinearAlloc* alloc,
84*795d594fSAndroid Build Coastguard Worker                                                                   const PointerSize pointer_size)
85*795d594fSAndroid Build Coastguard Worker                                                                   const {
86*795d594fSAndroid Build Coastguard Worker   // Presumably called from some sort of class visitor, no null pointers expected.
87*795d594fSAndroid Build Coastguard Worker   DCHECK(klass != nullptr);
88*795d594fSAndroid Build Coastguard Worker   DCHECK(alloc != nullptr);
89*795d594fSAndroid Build Coastguard Worker 
90*795d594fSAndroid Build Coastguard Worker   // Skip interfaces since they cannot provide SingleImplementations to work with.
91*795d594fSAndroid Build Coastguard Worker   if (klass->IsInterface()) {
92*795d594fSAndroid Build Coastguard Worker     return;
93*795d594fSAndroid Build Coastguard Worker   }
94*795d594fSAndroid Build Coastguard Worker 
95*795d594fSAndroid Build Coastguard Worker   // This method is called while visiting classes in the class table of a class loader.
96*795d594fSAndroid Build Coastguard Worker   // That means, some 'klass'es can belong to other classloaders. Argument 'alloc'
97*795d594fSAndroid Build Coastguard Worker   // allows to explicitly indicate a classloader, which is going to be deleted.
98*795d594fSAndroid Build Coastguard Worker   // Filter out classes, that do not belong to it.
99*795d594fSAndroid Build Coastguard Worker   if (!alloc->ContainsUnsafe(klass->GetMethodsPtr())) {
100*795d594fSAndroid Build Coastguard Worker     return;
101*795d594fSAndroid Build Coastguard Worker   }
102*795d594fSAndroid Build Coastguard Worker 
103*795d594fSAndroid Build Coastguard Worker   // CHA analysis is only applied to resolved classes.
104*795d594fSAndroid Build Coastguard Worker   if (!klass->IsResolved()) {
105*795d594fSAndroid Build Coastguard Worker     return;
106*795d594fSAndroid Build Coastguard Worker   }
107*795d594fSAndroid Build Coastguard Worker 
108*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> super = klass->GetSuperClass<kDefaultVerifyFlags, kWithoutReadBarrier>();
109*795d594fSAndroid Build Coastguard Worker 
110*795d594fSAndroid Build Coastguard Worker   // Skip Object class and primitive classes.
111*795d594fSAndroid Build Coastguard Worker   if (super == nullptr) {
112*795d594fSAndroid Build Coastguard Worker     return;
113*795d594fSAndroid Build Coastguard Worker   }
114*795d594fSAndroid Build Coastguard Worker 
115*795d594fSAndroid Build Coastguard Worker   // The class is going to be deleted. Iterate over the virtual methods of its superclasses to see
116*795d594fSAndroid Build Coastguard Worker   // if they have SingleImplementations methods defined by 'klass'.
117*795d594fSAndroid Build Coastguard Worker   // Skip all virtual methods that do not override methods from super class since they cannot be
118*795d594fSAndroid Build Coastguard Worker   // SingleImplementations for anything.
119*795d594fSAndroid Build Coastguard Worker   int32_t vtbl_size = super->GetVTableLength<kDefaultVerifyFlags>();
120*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::ClassLoader> loader =
121*795d594fSAndroid Build Coastguard Worker       klass->GetClassLoader<kDefaultVerifyFlags, kWithoutReadBarrier>();
122*795d594fSAndroid Build Coastguard Worker   for (int vtbl_index = 0; vtbl_index < vtbl_size; ++vtbl_index) {
123*795d594fSAndroid Build Coastguard Worker     ArtMethod* method =
124*795d594fSAndroid Build Coastguard Worker         klass->GetVTableEntry<kDefaultVerifyFlags, kWithoutReadBarrier>(vtbl_index, pointer_size);
125*795d594fSAndroid Build Coastguard Worker     if (!alloc->ContainsUnsafe(method)) {
126*795d594fSAndroid Build Coastguard Worker       continue;
127*795d594fSAndroid Build Coastguard Worker     }
128*795d594fSAndroid Build Coastguard Worker 
129*795d594fSAndroid Build Coastguard Worker     // Find all occurrences of virtual methods in parents' SingleImplementations fields
130*795d594fSAndroid Build Coastguard Worker     // and reset them.
131*795d594fSAndroid Build Coastguard Worker     // No need to reset SingleImplementations for the method itself (it will be cleared anyways),
132*795d594fSAndroid Build Coastguard Worker     // so start with a superclass and move up looking into a corresponding vtbl slot.
133*795d594fSAndroid Build Coastguard Worker     for (ObjPtr<mirror::Class> super_it = super;
134*795d594fSAndroid Build Coastguard Worker          super_it != nullptr &&
135*795d594fSAndroid Build Coastguard Worker              super_it->GetVTableLength<kDefaultVerifyFlags>() > vtbl_index;
136*795d594fSAndroid Build Coastguard Worker          super_it = super_it->GetSuperClass<kDefaultVerifyFlags, kWithoutReadBarrier>()) {
137*795d594fSAndroid Build Coastguard Worker       // Skip superclasses that are also going to be unloaded.
138*795d594fSAndroid Build Coastguard Worker       ObjPtr<mirror::ClassLoader> super_loader = super_it->
139*795d594fSAndroid Build Coastguard Worker           GetClassLoader<kDefaultVerifyFlags, kWithoutReadBarrier>();
140*795d594fSAndroid Build Coastguard Worker       if (super_loader == loader) {
141*795d594fSAndroid Build Coastguard Worker         continue;
142*795d594fSAndroid Build Coastguard Worker       }
143*795d594fSAndroid Build Coastguard Worker 
144*795d594fSAndroid Build Coastguard Worker       ArtMethod* super_method = super_it->
145*795d594fSAndroid Build Coastguard Worker           GetVTableEntry<kDefaultVerifyFlags, kWithoutReadBarrier>(vtbl_index, pointer_size);
146*795d594fSAndroid Build Coastguard Worker       if (super_method->IsAbstract() &&
147*795d594fSAndroid Build Coastguard Worker           super_method->HasSingleImplementation() &&
148*795d594fSAndroid Build Coastguard Worker           super_method->GetSingleImplementation(pointer_size) == method) {
149*795d594fSAndroid Build Coastguard Worker         // Do like there was no single implementation defined previously
150*795d594fSAndroid Build Coastguard Worker         // for this method of the superclass.
151*795d594fSAndroid Build Coastguard Worker         super_method->SetSingleImplementation(nullptr, pointer_size);
152*795d594fSAndroid Build Coastguard Worker       } else {
153*795d594fSAndroid Build Coastguard Worker         // No related SingleImplementations could possibly be found any further.
154*795d594fSAndroid Build Coastguard Worker         DCHECK(!super_method->HasSingleImplementation());
155*795d594fSAndroid Build Coastguard Worker         break;
156*795d594fSAndroid Build Coastguard Worker       }
157*795d594fSAndroid Build Coastguard Worker     }
158*795d594fSAndroid Build Coastguard Worker   }
159*795d594fSAndroid Build Coastguard Worker 
160*795d594fSAndroid Build Coastguard Worker   // Check all possible interface methods too.
161*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::IfTable> iftable = klass->GetIfTable<kDefaultVerifyFlags, kWithoutReadBarrier>();
162*795d594fSAndroid Build Coastguard Worker   const size_t ifcount = klass->GetIfTableCount<kDefaultVerifyFlags>();
163*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0; i < ifcount; ++i) {
164*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Class> interface =
165*795d594fSAndroid Build Coastguard Worker         iftable->GetInterface<kDefaultVerifyFlags, kWithoutReadBarrier>(i);
166*795d594fSAndroid Build Coastguard Worker     for (size_t j = 0,
167*795d594fSAndroid Build Coastguard Worker          count = iftable->GetMethodArrayCount<kDefaultVerifyFlags, kWithoutReadBarrier>(i);
168*795d594fSAndroid Build Coastguard Worker          j < count;
169*795d594fSAndroid Build Coastguard Worker          ++j) {
170*795d594fSAndroid Build Coastguard Worker       ArtMethod* method = interface->GetVirtualMethod(j, pointer_size);
171*795d594fSAndroid Build Coastguard Worker       if (method->HasSingleImplementation() &&
172*795d594fSAndroid Build Coastguard Worker           alloc->ContainsUnsafe(method->GetSingleImplementation(pointer_size)) &&
173*795d594fSAndroid Build Coastguard Worker           !method->IsDefault()) {
174*795d594fSAndroid Build Coastguard Worker         // Do like there was no single implementation defined previously for this method.
175*795d594fSAndroid Build Coastguard Worker         method->SetSingleImplementation(nullptr, pointer_size);
176*795d594fSAndroid Build Coastguard Worker       }
177*795d594fSAndroid Build Coastguard Worker     }
178*795d594fSAndroid Build Coastguard Worker   }
179*795d594fSAndroid Build Coastguard Worker }
180*795d594fSAndroid Build Coastguard Worker 
181*795d594fSAndroid Build Coastguard Worker // This stack visitor walks the stack and for compiled code with certain method
182*795d594fSAndroid Build Coastguard Worker // headers, sets the should_deoptimize flag on stack to 1.
183*795d594fSAndroid Build Coastguard Worker // TODO: also set the register value to 1 when should_deoptimize is allocated in
184*795d594fSAndroid Build Coastguard Worker // a register.
185*795d594fSAndroid Build Coastguard Worker class CHAStackVisitor final  : public StackVisitor {
186*795d594fSAndroid Build Coastguard Worker  public:
CHAStackVisitor(Thread * thread_in,Context * context,const std::unordered_set<OatQuickMethodHeader * > & method_headers)187*795d594fSAndroid Build Coastguard Worker   CHAStackVisitor(Thread* thread_in,
188*795d594fSAndroid Build Coastguard Worker                   Context* context,
189*795d594fSAndroid Build Coastguard Worker                   const std::unordered_set<OatQuickMethodHeader*>& method_headers)
190*795d594fSAndroid Build Coastguard Worker       : StackVisitor(thread_in, context, StackVisitor::StackWalkKind::kSkipInlinedFrames),
191*795d594fSAndroid Build Coastguard Worker         method_headers_(method_headers) {
192*795d594fSAndroid Build Coastguard Worker   }
193*795d594fSAndroid Build Coastguard Worker 
VisitFrame()194*795d594fSAndroid Build Coastguard Worker   bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) {
195*795d594fSAndroid Build Coastguard Worker     ArtMethod* method = GetMethod();
196*795d594fSAndroid Build Coastguard Worker     // Avoid types of methods that do not have an oat quick method header.
197*795d594fSAndroid Build Coastguard Worker     if (method == nullptr ||
198*795d594fSAndroid Build Coastguard Worker         method->IsRuntimeMethod() ||
199*795d594fSAndroid Build Coastguard Worker         method->IsNative() ||
200*795d594fSAndroid Build Coastguard Worker         method->IsProxyMethod()) {
201*795d594fSAndroid Build Coastguard Worker       return true;
202*795d594fSAndroid Build Coastguard Worker     }
203*795d594fSAndroid Build Coastguard Worker     if (GetCurrentQuickFrame() == nullptr) {
204*795d594fSAndroid Build Coastguard Worker       // Not compiled code.
205*795d594fSAndroid Build Coastguard Worker       return true;
206*795d594fSAndroid Build Coastguard Worker     }
207*795d594fSAndroid Build Coastguard Worker     // Method may have multiple versions of compiled code. Check
208*795d594fSAndroid Build Coastguard Worker     // the method header to see if it has should_deoptimize flag.
209*795d594fSAndroid Build Coastguard Worker     const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
210*795d594fSAndroid Build Coastguard Worker     DCHECK(method_header != nullptr);
211*795d594fSAndroid Build Coastguard Worker     if (!method_header->HasShouldDeoptimizeFlag()) {
212*795d594fSAndroid Build Coastguard Worker       // This compiled version doesn't have should_deoptimize flag. Skip.
213*795d594fSAndroid Build Coastguard Worker       return true;
214*795d594fSAndroid Build Coastguard Worker     }
215*795d594fSAndroid Build Coastguard Worker     auto it = std::find(method_headers_.begin(), method_headers_.end(), method_header);
216*795d594fSAndroid Build Coastguard Worker     if (it == method_headers_.end()) {
217*795d594fSAndroid Build Coastguard Worker       // Not in the list of method headers that should be deoptimized.
218*795d594fSAndroid Build Coastguard Worker       return true;
219*795d594fSAndroid Build Coastguard Worker     }
220*795d594fSAndroid Build Coastguard Worker 
221*795d594fSAndroid Build Coastguard Worker     // The compiled code on stack is not valid anymore. Need to deoptimize.
222*795d594fSAndroid Build Coastguard Worker     SetShouldDeoptimizeFlag(DeoptimizeFlagValue::kCHA);
223*795d594fSAndroid Build Coastguard Worker 
224*795d594fSAndroid Build Coastguard Worker     return true;
225*795d594fSAndroid Build Coastguard Worker   }
226*795d594fSAndroid Build Coastguard Worker 
227*795d594fSAndroid Build Coastguard Worker  private:
228*795d594fSAndroid Build Coastguard Worker   // Set of method headers for compiled code that should be deoptimized.
229*795d594fSAndroid Build Coastguard Worker   const std::unordered_set<OatQuickMethodHeader*>& method_headers_;
230*795d594fSAndroid Build Coastguard Worker 
231*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(CHAStackVisitor);
232*795d594fSAndroid Build Coastguard Worker };
233*795d594fSAndroid Build Coastguard Worker 
234*795d594fSAndroid Build Coastguard Worker class CHACheckpoint final : public Closure {
235*795d594fSAndroid Build Coastguard Worker  public:
CHACheckpoint(const std::unordered_set<OatQuickMethodHeader * > & method_headers)236*795d594fSAndroid Build Coastguard Worker   explicit CHACheckpoint(const std::unordered_set<OatQuickMethodHeader*>& method_headers)
237*795d594fSAndroid Build Coastguard Worker       : barrier_(0),
238*795d594fSAndroid Build Coastguard Worker         method_headers_(method_headers) {}
239*795d594fSAndroid Build Coastguard Worker 
Run(Thread * thread)240*795d594fSAndroid Build Coastguard Worker   void Run(Thread* thread) override REQUIRES_SHARED(Locks::mutator_lock_) {
241*795d594fSAndroid Build Coastguard Worker     // Note thread and self may not be equal if thread was already suspended at
242*795d594fSAndroid Build Coastguard Worker     // the point of the request.
243*795d594fSAndroid Build Coastguard Worker     Thread* self = Thread::Current();
244*795d594fSAndroid Build Coastguard Worker     CHAStackVisitor visitor(thread, nullptr, method_headers_);
245*795d594fSAndroid Build Coastguard Worker     visitor.WalkStack();
246*795d594fSAndroid Build Coastguard Worker     barrier_.Pass(self);
247*795d594fSAndroid Build Coastguard Worker   }
248*795d594fSAndroid Build Coastguard Worker 
WaitForThreadsToRunThroughCheckpoint(size_t threads_running_checkpoint)249*795d594fSAndroid Build Coastguard Worker   void WaitForThreadsToRunThroughCheckpoint(size_t threads_running_checkpoint) {
250*795d594fSAndroid Build Coastguard Worker     Thread* self = Thread::Current();
251*795d594fSAndroid Build Coastguard Worker     ScopedThreadStateChange tsc(self, ThreadState::kWaitingForCheckPointsToRun);
252*795d594fSAndroid Build Coastguard Worker     barrier_.Increment(self, threads_running_checkpoint);
253*795d594fSAndroid Build Coastguard Worker   }
254*795d594fSAndroid Build Coastguard Worker 
255*795d594fSAndroid Build Coastguard Worker  private:
256*795d594fSAndroid Build Coastguard Worker   // The barrier to be passed through and for the requestor to wait upon.
257*795d594fSAndroid Build Coastguard Worker   Barrier barrier_;
258*795d594fSAndroid Build Coastguard Worker   // List of method headers for invalidated compiled code.
259*795d594fSAndroid Build Coastguard Worker   const std::unordered_set<OatQuickMethodHeader*>& method_headers_;
260*795d594fSAndroid Build Coastguard Worker 
261*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(CHACheckpoint);
262*795d594fSAndroid Build Coastguard Worker };
263*795d594fSAndroid Build Coastguard Worker 
264*795d594fSAndroid Build Coastguard Worker 
VerifyNonSingleImplementation(ObjPtr<mirror::Class> verify_class,uint16_t verify_index,ArtMethod * excluded_method)265*795d594fSAndroid Build Coastguard Worker static void VerifyNonSingleImplementation(ObjPtr<mirror::Class> verify_class,
266*795d594fSAndroid Build Coastguard Worker                                           uint16_t verify_index,
267*795d594fSAndroid Build Coastguard Worker                                           ArtMethod* excluded_method)
268*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
269*795d594fSAndroid Build Coastguard Worker   if (!kIsDebugBuild) {
270*795d594fSAndroid Build Coastguard Worker     return;
271*795d594fSAndroid Build Coastguard Worker   }
272*795d594fSAndroid Build Coastguard Worker 
273*795d594fSAndroid Build Coastguard Worker   // Grab cha_lock_ to make sure all single-implementation updates are seen.
274*795d594fSAndroid Build Coastguard Worker   MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
275*795d594fSAndroid Build Coastguard Worker 
276*795d594fSAndroid Build Coastguard Worker   PointerSize image_pointer_size =
277*795d594fSAndroid Build Coastguard Worker       Runtime::Current()->GetClassLinker()->GetImagePointerSize();
278*795d594fSAndroid Build Coastguard Worker 
279*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> input_verify_class = verify_class;
280*795d594fSAndroid Build Coastguard Worker 
281*795d594fSAndroid Build Coastguard Worker   while (verify_class != nullptr) {
282*795d594fSAndroid Build Coastguard Worker     if (verify_index >= verify_class->GetVTableLength()) {
283*795d594fSAndroid Build Coastguard Worker       return;
284*795d594fSAndroid Build Coastguard Worker     }
285*795d594fSAndroid Build Coastguard Worker     ArtMethod* verify_method = verify_class->GetVTableEntry(verify_index, image_pointer_size);
286*795d594fSAndroid Build Coastguard Worker     if (verify_method != excluded_method) {
287*795d594fSAndroid Build Coastguard Worker       auto construct_parent_chain = [](ObjPtr<mirror::Class> failed, ObjPtr<mirror::Class> in)
288*795d594fSAndroid Build Coastguard Worker           REQUIRES_SHARED(Locks::mutator_lock_) {
289*795d594fSAndroid Build Coastguard Worker         std::string tmp = in->PrettyClass();
290*795d594fSAndroid Build Coastguard Worker         while (in != failed) {
291*795d594fSAndroid Build Coastguard Worker           in = in->GetSuperClass();
292*795d594fSAndroid Build Coastguard Worker           tmp += "->" + in->PrettyClass();
293*795d594fSAndroid Build Coastguard Worker         }
294*795d594fSAndroid Build Coastguard Worker         return tmp;
295*795d594fSAndroid Build Coastguard Worker       };
296*795d594fSAndroid Build Coastguard Worker       DCHECK(!verify_method->HasSingleImplementation())
297*795d594fSAndroid Build Coastguard Worker           << "class: " << verify_class->PrettyClass()
298*795d594fSAndroid Build Coastguard Worker           << " verify_method: " << verify_method->PrettyMethod(true)
299*795d594fSAndroid Build Coastguard Worker           << " (" << construct_parent_chain(verify_class, input_verify_class) << ")"
300*795d594fSAndroid Build Coastguard Worker           << " excluded_method: " << ArtMethod::PrettyMethod(excluded_method);
301*795d594fSAndroid Build Coastguard Worker       if (verify_method->IsAbstract()) {
302*795d594fSAndroid Build Coastguard Worker         DCHECK(verify_method->GetSingleImplementation(image_pointer_size) == nullptr);
303*795d594fSAndroid Build Coastguard Worker       }
304*795d594fSAndroid Build Coastguard Worker     }
305*795d594fSAndroid Build Coastguard Worker     verify_class = verify_class->GetSuperClass();
306*795d594fSAndroid Build Coastguard Worker   }
307*795d594fSAndroid Build Coastguard Worker }
308*795d594fSAndroid Build Coastguard Worker 
CheckVirtualMethodSingleImplementationInfo(Handle<mirror::Class> klass,ArtMethod * virtual_method,ArtMethod * method_in_super,std::unordered_set<ArtMethod * > & invalidated_single_impl_methods,PointerSize pointer_size)309*795d594fSAndroid Build Coastguard Worker void ClassHierarchyAnalysis::CheckVirtualMethodSingleImplementationInfo(
310*795d594fSAndroid Build Coastguard Worker     Handle<mirror::Class> klass,
311*795d594fSAndroid Build Coastguard Worker     ArtMethod* virtual_method,
312*795d594fSAndroid Build Coastguard Worker     ArtMethod* method_in_super,
313*795d594fSAndroid Build Coastguard Worker     std::unordered_set<ArtMethod*>& invalidated_single_impl_methods,
314*795d594fSAndroid Build Coastguard Worker     PointerSize pointer_size) {
315*795d594fSAndroid Build Coastguard Worker   // TODO: if klass is not instantiable, virtual_method isn't invocable yet so
316*795d594fSAndroid Build Coastguard Worker   // even if it overrides, it doesn't invalidate single-implementation
317*795d594fSAndroid Build Coastguard Worker   // assumption.
318*795d594fSAndroid Build Coastguard Worker 
319*795d594fSAndroid Build Coastguard Worker   DCHECK_IMPLIES(virtual_method == method_in_super, virtual_method->IsAbstract());
320*795d594fSAndroid Build Coastguard Worker   DCHECK(method_in_super->GetDeclaringClass()->IsResolved()) << "class isn't resolved";
321*795d594fSAndroid Build Coastguard Worker   // If virtual_method doesn't come from a default interface method, it should
322*795d594fSAndroid Build Coastguard Worker   // be supplied by klass.
323*795d594fSAndroid Build Coastguard Worker   DCHECK(virtual_method == method_in_super ||
324*795d594fSAndroid Build Coastguard Worker          virtual_method->IsCopied() ||
325*795d594fSAndroid Build Coastguard Worker          virtual_method->GetDeclaringClass() == klass.Get());
326*795d594fSAndroid Build Coastguard Worker 
327*795d594fSAndroid Build Coastguard Worker   // To make updating single-implementation flags simple, we always maintain the following
328*795d594fSAndroid Build Coastguard Worker   // invariant:
329*795d594fSAndroid Build Coastguard Worker   // Say all virtual methods in the same vtable slot, starting from the bottom child class
330*795d594fSAndroid Build Coastguard Worker   // to super classes, is a sequence of unique methods m3, m2, m1, ... (after removing duplicate
331*795d594fSAndroid Build Coastguard Worker   // methods for inherited methods).
332*795d594fSAndroid Build Coastguard Worker   // For example for the following class hierarchy,
333*795d594fSAndroid Build Coastguard Worker   //   class A { void m() { ... } }
334*795d594fSAndroid Build Coastguard Worker   //   class B extends A { void m() { ... } }
335*795d594fSAndroid Build Coastguard Worker   //   class C extends B {}
336*795d594fSAndroid Build Coastguard Worker   //   class D extends C { void m() { ... } }
337*795d594fSAndroid Build Coastguard Worker   // the sequence is D.m(), B.m(), A.m().
338*795d594fSAndroid Build Coastguard Worker   // The single-implementation status for that sequence of methods begin with one or two true's,
339*795d594fSAndroid Build Coastguard Worker   // then become all falses. The only case where two true's are possible is for one abstract
340*795d594fSAndroid Build Coastguard Worker   // method m and one non-abstract method mImpl that overrides method m.
341*795d594fSAndroid Build Coastguard Worker   // With the invariant, when linking in a new class, we only need to at most update one or
342*795d594fSAndroid Build Coastguard Worker   // two methods in the sequence for their single-implementation status, in order to maintain
343*795d594fSAndroid Build Coastguard Worker   // the invariant.
344*795d594fSAndroid Build Coastguard Worker 
345*795d594fSAndroid Build Coastguard Worker   if (!method_in_super->HasSingleImplementation()) {
346*795d594fSAndroid Build Coastguard Worker     // method_in_super already has multiple implementations. All methods in the
347*795d594fSAndroid Build Coastguard Worker     // same vtable slots in its super classes should have
348*795d594fSAndroid Build Coastguard Worker     // non-single-implementation already.
349*795d594fSAndroid Build Coastguard Worker     VerifyNonSingleImplementation(klass->GetSuperClass()->GetSuperClass(),
350*795d594fSAndroid Build Coastguard Worker                                   method_in_super->GetMethodIndex(),
351*795d594fSAndroid Build Coastguard Worker                                   /* excluded_method= */ nullptr);
352*795d594fSAndroid Build Coastguard Worker     return;
353*795d594fSAndroid Build Coastguard Worker   }
354*795d594fSAndroid Build Coastguard Worker 
355*795d594fSAndroid Build Coastguard Worker   uint16_t method_index = method_in_super->GetMethodIndex();
356*795d594fSAndroid Build Coastguard Worker   if (method_in_super->IsAbstract()) {
357*795d594fSAndroid Build Coastguard Worker     // An abstract method should have made all methods in the same vtable
358*795d594fSAndroid Build Coastguard Worker     // slot above it in the class hierarchy having non-single-implementation.
359*795d594fSAndroid Build Coastguard Worker     VerifyNonSingleImplementation(klass->GetSuperClass()->GetSuperClass(),
360*795d594fSAndroid Build Coastguard Worker                                   method_index,
361*795d594fSAndroid Build Coastguard Worker                                   method_in_super);
362*795d594fSAndroid Build Coastguard Worker 
363*795d594fSAndroid Build Coastguard Worker     if (virtual_method->IsAbstract()) {
364*795d594fSAndroid Build Coastguard Worker       // SUPER: abstract, VIRTUAL: abstract.
365*795d594fSAndroid Build Coastguard Worker       if (method_in_super == virtual_method) {
366*795d594fSAndroid Build Coastguard Worker         DCHECK(klass->IsInstantiable());
367*795d594fSAndroid Build Coastguard Worker         // An instantiable subclass hasn't provided a concrete implementation of
368*795d594fSAndroid Build Coastguard Worker         // the abstract method. Invoking method_in_super may throw AbstractMethodError.
369*795d594fSAndroid Build Coastguard Worker         // This is an uncommon case, so we simply treat method_in_super as not
370*795d594fSAndroid Build Coastguard Worker         // having single-implementation.
371*795d594fSAndroid Build Coastguard Worker         invalidated_single_impl_methods.insert(method_in_super);
372*795d594fSAndroid Build Coastguard Worker         return;
373*795d594fSAndroid Build Coastguard Worker       } else {
374*795d594fSAndroid Build Coastguard Worker         // One abstract method overrides another abstract method. This is an uncommon
375*795d594fSAndroid Build Coastguard Worker         // case. We simply treat method_in_super as not having single-implementation.
376*795d594fSAndroid Build Coastguard Worker         invalidated_single_impl_methods.insert(method_in_super);
377*795d594fSAndroid Build Coastguard Worker         return;
378*795d594fSAndroid Build Coastguard Worker       }
379*795d594fSAndroid Build Coastguard Worker     } else {
380*795d594fSAndroid Build Coastguard Worker       // SUPER: abstract, VIRTUAL: non-abstract.
381*795d594fSAndroid Build Coastguard Worker       // A non-abstract method overrides an abstract method.
382*795d594fSAndroid Build Coastguard Worker       if (!virtual_method->IsDefaultConflicting() &&
383*795d594fSAndroid Build Coastguard Worker           method_in_super->GetSingleImplementation(pointer_size) == nullptr) {
384*795d594fSAndroid Build Coastguard Worker         // Abstract method_in_super has no implementation yet.
385*795d594fSAndroid Build Coastguard Worker         // We need to grab cha_lock_ since there may be multiple class linking
386*795d594fSAndroid Build Coastguard Worker         // going on that can check/modify the single-implementation flag/method
387*795d594fSAndroid Build Coastguard Worker         // of method_in_super.
388*795d594fSAndroid Build Coastguard Worker         MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
389*795d594fSAndroid Build Coastguard Worker         if (!method_in_super->HasSingleImplementation()) {
390*795d594fSAndroid Build Coastguard Worker           return;
391*795d594fSAndroid Build Coastguard Worker         }
392*795d594fSAndroid Build Coastguard Worker         if (method_in_super->GetSingleImplementation(pointer_size) == nullptr) {
393*795d594fSAndroid Build Coastguard Worker           // virtual_method becomes the first implementation for method_in_super.
394*795d594fSAndroid Build Coastguard Worker           method_in_super->SetSingleImplementation(virtual_method, pointer_size);
395*795d594fSAndroid Build Coastguard Worker           // Keep method_in_super's single-implementation status.
396*795d594fSAndroid Build Coastguard Worker           return;
397*795d594fSAndroid Build Coastguard Worker         }
398*795d594fSAndroid Build Coastguard Worker         // Fall through to invalidate method_in_super's single-implementation status.
399*795d594fSAndroid Build Coastguard Worker       }
400*795d594fSAndroid Build Coastguard Worker       // Abstract method_in_super already got one implementation.
401*795d594fSAndroid Build Coastguard Worker       // Invalidate method_in_super's single-implementation status.
402*795d594fSAndroid Build Coastguard Worker       invalidated_single_impl_methods.insert(method_in_super);
403*795d594fSAndroid Build Coastguard Worker       return;
404*795d594fSAndroid Build Coastguard Worker     }
405*795d594fSAndroid Build Coastguard Worker   } else {
406*795d594fSAndroid Build Coastguard Worker     if (virtual_method->IsAbstract()) {
407*795d594fSAndroid Build Coastguard Worker       // SUPER: non-abstract, VIRTUAL: abstract.
408*795d594fSAndroid Build Coastguard Worker       // An abstract method overrides a non-abstract method. This is an uncommon
409*795d594fSAndroid Build Coastguard Worker       // case, we simply treat both methods as not having single-implementation.
410*795d594fSAndroid Build Coastguard Worker       invalidated_single_impl_methods.insert(virtual_method);
411*795d594fSAndroid Build Coastguard Worker       // Fall-through to handle invalidating method_in_super of its
412*795d594fSAndroid Build Coastguard Worker       // single-implementation status.
413*795d594fSAndroid Build Coastguard Worker     }
414*795d594fSAndroid Build Coastguard Worker 
415*795d594fSAndroid Build Coastguard Worker     // SUPER: non-abstract, VIRTUAL: non-abstract/abstract(fall-through from previous if).
416*795d594fSAndroid Build Coastguard Worker     // Invalidate method_in_super's single-implementation status.
417*795d594fSAndroid Build Coastguard Worker     invalidated_single_impl_methods.insert(method_in_super);
418*795d594fSAndroid Build Coastguard Worker 
419*795d594fSAndroid Build Coastguard Worker     // method_in_super might be the single-implementation of another abstract method,
420*795d594fSAndroid Build Coastguard Worker     // which should be also invalidated of its single-implementation status.
421*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Class> super_super = klass->GetSuperClass()->GetSuperClass();
422*795d594fSAndroid Build Coastguard Worker     while (super_super != nullptr &&
423*795d594fSAndroid Build Coastguard Worker            method_index < super_super->GetVTableLength()) {
424*795d594fSAndroid Build Coastguard Worker       ArtMethod* method_in_super_super = super_super->GetVTableEntry(method_index, pointer_size);
425*795d594fSAndroid Build Coastguard Worker       if (method_in_super_super != method_in_super) {
426*795d594fSAndroid Build Coastguard Worker         if (method_in_super_super->IsAbstract()) {
427*795d594fSAndroid Build Coastguard Worker           if (method_in_super_super->HasSingleImplementation()) {
428*795d594fSAndroid Build Coastguard Worker             // Invalidate method_in_super's single-implementation status.
429*795d594fSAndroid Build Coastguard Worker             invalidated_single_impl_methods.insert(method_in_super_super);
430*795d594fSAndroid Build Coastguard Worker             // No need to further traverse up the class hierarchy since if there
431*795d594fSAndroid Build Coastguard Worker             // are cases that one abstract method overrides another method, we
432*795d594fSAndroid Build Coastguard Worker             // should have made that method having non-single-implementation already.
433*795d594fSAndroid Build Coastguard Worker           } else {
434*795d594fSAndroid Build Coastguard Worker             // method_in_super_super is already non-single-implementation.
435*795d594fSAndroid Build Coastguard Worker             // No need to further traverse up the class hierarchy.
436*795d594fSAndroid Build Coastguard Worker           }
437*795d594fSAndroid Build Coastguard Worker         } else {
438*795d594fSAndroid Build Coastguard Worker           DCHECK(!method_in_super_super->HasSingleImplementation());
439*795d594fSAndroid Build Coastguard Worker           // No need to further traverse up the class hierarchy since two non-abstract
440*795d594fSAndroid Build Coastguard Worker           // methods (method_in_super and method_in_super_super) should have set all
441*795d594fSAndroid Build Coastguard Worker           // other methods (abstract or not) in the vtable slot to be non-single-implementation.
442*795d594fSAndroid Build Coastguard Worker         }
443*795d594fSAndroid Build Coastguard Worker 
444*795d594fSAndroid Build Coastguard Worker         VerifyNonSingleImplementation(super_super->GetSuperClass(),
445*795d594fSAndroid Build Coastguard Worker                                       method_index,
446*795d594fSAndroid Build Coastguard Worker                                       method_in_super_super);
447*795d594fSAndroid Build Coastguard Worker         // No need to go any further.
448*795d594fSAndroid Build Coastguard Worker         return;
449*795d594fSAndroid Build Coastguard Worker       } else {
450*795d594fSAndroid Build Coastguard Worker         super_super = super_super->GetSuperClass();
451*795d594fSAndroid Build Coastguard Worker       }
452*795d594fSAndroid Build Coastguard Worker     }
453*795d594fSAndroid Build Coastguard Worker   }
454*795d594fSAndroid Build Coastguard Worker }
455*795d594fSAndroid Build Coastguard Worker 
CheckInterfaceMethodSingleImplementationInfo(Handle<mirror::Class> klass,ArtMethod * interface_method,ArtMethod * implementation_method,std::unordered_set<ArtMethod * > & invalidated_single_impl_methods,PointerSize pointer_size)456*795d594fSAndroid Build Coastguard Worker void ClassHierarchyAnalysis::CheckInterfaceMethodSingleImplementationInfo(
457*795d594fSAndroid Build Coastguard Worker     Handle<mirror::Class> klass,
458*795d594fSAndroid Build Coastguard Worker     ArtMethod* interface_method,
459*795d594fSAndroid Build Coastguard Worker     ArtMethod* implementation_method,
460*795d594fSAndroid Build Coastguard Worker     std::unordered_set<ArtMethod*>& invalidated_single_impl_methods,
461*795d594fSAndroid Build Coastguard Worker     PointerSize pointer_size) {
462*795d594fSAndroid Build Coastguard Worker   DCHECK(klass->IsInstantiable());
463*795d594fSAndroid Build Coastguard Worker   DCHECK(interface_method->IsAbstract() || interface_method->IsDefault());
464*795d594fSAndroid Build Coastguard Worker 
465*795d594fSAndroid Build Coastguard Worker   if (!interface_method->HasSingleImplementation()) {
466*795d594fSAndroid Build Coastguard Worker     return;
467*795d594fSAndroid Build Coastguard Worker   }
468*795d594fSAndroid Build Coastguard Worker 
469*795d594fSAndroid Build Coastguard Worker   if (!implementation_method->IsInvokable()) {
470*795d594fSAndroid Build Coastguard Worker     DCHECK(implementation_method->IsAbstract() || implementation_method->IsDefaultConflicting());
471*795d594fSAndroid Build Coastguard Worker     // An instantiable class doesn't supply an implementation for interface_method,
472*795d594fSAndroid Build Coastguard Worker     // or has conflicting default method implementations. Invoking the interface method
473*795d594fSAndroid Build Coastguard Worker     // on the  class will throw AbstractMethodError or IncompatibleClassChangeError.
474*795d594fSAndroid Build Coastguard Worker     // (Note: The RI throws AME instead of ICCE for default conflict.) This is an uncommon
475*795d594fSAndroid Build Coastguard Worker     // case, so we simply treat interface_method as not having single-implementation.
476*795d594fSAndroid Build Coastguard Worker     invalidated_single_impl_methods.insert(interface_method);
477*795d594fSAndroid Build Coastguard Worker     return;
478*795d594fSAndroid Build Coastguard Worker   }
479*795d594fSAndroid Build Coastguard Worker 
480*795d594fSAndroid Build Coastguard Worker   // We need to grab cha_lock_ since there may be multiple class linking going
481*795d594fSAndroid Build Coastguard Worker   // on that can check/modify the single-implementation flag/method of
482*795d594fSAndroid Build Coastguard Worker   // interface_method.
483*795d594fSAndroid Build Coastguard Worker   MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
484*795d594fSAndroid Build Coastguard Worker   // Do this check again after we grab cha_lock_.
485*795d594fSAndroid Build Coastguard Worker   if (!interface_method->HasSingleImplementation()) {
486*795d594fSAndroid Build Coastguard Worker     return;
487*795d594fSAndroid Build Coastguard Worker   }
488*795d594fSAndroid Build Coastguard Worker 
489*795d594fSAndroid Build Coastguard Worker   ArtMethod* single_impl = interface_method->GetSingleImplementation(pointer_size);
490*795d594fSAndroid Build Coastguard Worker   if (single_impl == nullptr) {
491*795d594fSAndroid Build Coastguard Worker     // implementation_method becomes the first implementation for
492*795d594fSAndroid Build Coastguard Worker     // interface_method.
493*795d594fSAndroid Build Coastguard Worker     interface_method->SetSingleImplementation(implementation_method, pointer_size);
494*795d594fSAndroid Build Coastguard Worker     // Keep interface_method's single-implementation status.
495*795d594fSAndroid Build Coastguard Worker     return;
496*795d594fSAndroid Build Coastguard Worker   }
497*795d594fSAndroid Build Coastguard Worker   DCHECK(single_impl->IsInvokable());
498*795d594fSAndroid Build Coastguard Worker   if ((single_impl->GetDeclaringClass() == implementation_method->GetDeclaringClass())) {
499*795d594fSAndroid Build Coastguard Worker     // Same implementation. Since implementation_method may be a copy of a default
500*795d594fSAndroid Build Coastguard Worker     // method, we need to check the declaring class for equality.
501*795d594fSAndroid Build Coastguard Worker     return;
502*795d594fSAndroid Build Coastguard Worker   }
503*795d594fSAndroid Build Coastguard Worker   // Another implementation for interface_method.
504*795d594fSAndroid Build Coastguard Worker   invalidated_single_impl_methods.insert(interface_method);
505*795d594fSAndroid Build Coastguard Worker }
506*795d594fSAndroid Build Coastguard Worker 
InitSingleImplementationFlag(Handle<mirror::Class> klass,ArtMethod * method,PointerSize pointer_size)507*795d594fSAndroid Build Coastguard Worker void ClassHierarchyAnalysis::InitSingleImplementationFlag(Handle<mirror::Class> klass,
508*795d594fSAndroid Build Coastguard Worker                                                           ArtMethod* method,
509*795d594fSAndroid Build Coastguard Worker                                                           PointerSize pointer_size) {
510*795d594fSAndroid Build Coastguard Worker   DCHECK(method->IsCopied() || method->GetDeclaringClass() == klass.Get());
511*795d594fSAndroid Build Coastguard Worker   if (klass->IsFinal() || method->IsFinal()) {
512*795d594fSAndroid Build Coastguard Worker     // Final classes or methods do not need CHA for devirtualization.
513*795d594fSAndroid Build Coastguard Worker     // This frees up modifier bits for intrinsics which currently are only
514*795d594fSAndroid Build Coastguard Worker     // used for static methods or methods of final classes.
515*795d594fSAndroid Build Coastguard Worker     return;
516*795d594fSAndroid Build Coastguard Worker   }
517*795d594fSAndroid Build Coastguard Worker   if (method->IsAbstract()) {
518*795d594fSAndroid Build Coastguard Worker     // single-implementation of abstract method shares the same field
519*795d594fSAndroid Build Coastguard Worker     // that's used for JNI function of native method. It's fine since a method
520*795d594fSAndroid Build Coastguard Worker     // cannot be both abstract and native.
521*795d594fSAndroid Build Coastguard Worker     DCHECK(!method->IsNative()) << "Abstract method cannot be native";
522*795d594fSAndroid Build Coastguard Worker 
523*795d594fSAndroid Build Coastguard Worker     if (method->GetDeclaringClass()->IsInstantiable()) {
524*795d594fSAndroid Build Coastguard Worker       // Rare case, but we do accept it (such as 800-smali/smali/b_26143249.smali).
525*795d594fSAndroid Build Coastguard Worker       // Do not attempt to devirtualize it.
526*795d594fSAndroid Build Coastguard Worker       method->SetHasSingleImplementation(false);
527*795d594fSAndroid Build Coastguard Worker       DCHECK(method->GetSingleImplementation(pointer_size) == nullptr);
528*795d594fSAndroid Build Coastguard Worker     } else {
529*795d594fSAndroid Build Coastguard Worker       // Abstract method starts with single-implementation flag set and null
530*795d594fSAndroid Build Coastguard Worker       // implementation method.
531*795d594fSAndroid Build Coastguard Worker       method->SetHasSingleImplementation(true);
532*795d594fSAndroid Build Coastguard Worker       DCHECK(!method->HasCodeItem()) << method->PrettyMethod();
533*795d594fSAndroid Build Coastguard Worker       DCHECK(method->GetSingleImplementation(pointer_size) == nullptr) << method->PrettyMethod();
534*795d594fSAndroid Build Coastguard Worker     }
535*795d594fSAndroid Build Coastguard Worker   // Default conflicting methods cannot be treated with single implementations,
536*795d594fSAndroid Build Coastguard Worker   // as we need to call them (and not inline them) in case of ICCE.
537*795d594fSAndroid Build Coastguard Worker   // See class_linker.cc:EnsureThrowsInvocationError.
538*795d594fSAndroid Build Coastguard Worker   } else if (!method->IsDefaultConflicting()) {
539*795d594fSAndroid Build Coastguard Worker     method->SetHasSingleImplementation(true);
540*795d594fSAndroid Build Coastguard Worker     // Single implementation of non-abstract method is itself.
541*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(method->GetSingleImplementation(pointer_size), method);
542*795d594fSAndroid Build Coastguard Worker   }
543*795d594fSAndroid Build Coastguard Worker }
544*795d594fSAndroid Build Coastguard Worker 
UpdateAfterLoadingOf(Handle<mirror::Class> klass)545*795d594fSAndroid Build Coastguard Worker void ClassHierarchyAnalysis::UpdateAfterLoadingOf(Handle<mirror::Class> klass) {
546*795d594fSAndroid Build Coastguard Worker   PointerSize image_pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
547*795d594fSAndroid Build Coastguard Worker   if (klass->IsInterface()) {
548*795d594fSAndroid Build Coastguard Worker     for (ArtMethod& method : klass->GetDeclaredVirtualMethods(image_pointer_size)) {
549*795d594fSAndroid Build Coastguard Worker       DCHECK(method.IsAbstract() || method.IsDefault());
550*795d594fSAndroid Build Coastguard Worker       InitSingleImplementationFlag(klass, &method, image_pointer_size);
551*795d594fSAndroid Build Coastguard Worker     }
552*795d594fSAndroid Build Coastguard Worker     return;
553*795d594fSAndroid Build Coastguard Worker   }
554*795d594fSAndroid Build Coastguard Worker 
555*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> super_class = klass->GetSuperClass();
556*795d594fSAndroid Build Coastguard Worker   if (super_class == nullptr) {
557*795d594fSAndroid Build Coastguard Worker     return;
558*795d594fSAndroid Build Coastguard Worker   }
559*795d594fSAndroid Build Coastguard Worker 
560*795d594fSAndroid Build Coastguard Worker   // Keeps track of all methods whose single-implementation assumption
561*795d594fSAndroid Build Coastguard Worker   // is invalidated by linking `klass`.
562*795d594fSAndroid Build Coastguard Worker   std::unordered_set<ArtMethod*> invalidated_single_impl_methods;
563*795d594fSAndroid Build Coastguard Worker 
564*795d594fSAndroid Build Coastguard Worker   // Do an entry-by-entry comparison of vtable contents with super's vtable.
565*795d594fSAndroid Build Coastguard Worker   for (int32_t i = 0; i < super_class->GetVTableLength(); ++i) {
566*795d594fSAndroid Build Coastguard Worker     ArtMethod* method = klass->GetVTableEntry(i, image_pointer_size);
567*795d594fSAndroid Build Coastguard Worker     ArtMethod* method_in_super = super_class->GetVTableEntry(i, image_pointer_size);
568*795d594fSAndroid Build Coastguard Worker     if (method == method_in_super) {
569*795d594fSAndroid Build Coastguard Worker       // vtable slot entry is inherited from super class.
570*795d594fSAndroid Build Coastguard Worker       if (method->IsAbstract() && klass->IsInstantiable()) {
571*795d594fSAndroid Build Coastguard Worker         // An instantiable class that inherits an abstract method is treated as
572*795d594fSAndroid Build Coastguard Worker         // supplying an implementation that throws AbstractMethodError.
573*795d594fSAndroid Build Coastguard Worker         CheckVirtualMethodSingleImplementationInfo(klass,
574*795d594fSAndroid Build Coastguard Worker                                                    method,
575*795d594fSAndroid Build Coastguard Worker                                                    method_in_super,
576*795d594fSAndroid Build Coastguard Worker                                                    invalidated_single_impl_methods,
577*795d594fSAndroid Build Coastguard Worker                                                    image_pointer_size);
578*795d594fSAndroid Build Coastguard Worker       }
579*795d594fSAndroid Build Coastguard Worker       continue;
580*795d594fSAndroid Build Coastguard Worker     }
581*795d594fSAndroid Build Coastguard Worker     InitSingleImplementationFlag(klass, method, image_pointer_size);
582*795d594fSAndroid Build Coastguard Worker     CheckVirtualMethodSingleImplementationInfo(klass,
583*795d594fSAndroid Build Coastguard Worker                                                method,
584*795d594fSAndroid Build Coastguard Worker                                                method_in_super,
585*795d594fSAndroid Build Coastguard Worker                                                invalidated_single_impl_methods,
586*795d594fSAndroid Build Coastguard Worker                                                image_pointer_size);
587*795d594fSAndroid Build Coastguard Worker   }
588*795d594fSAndroid Build Coastguard Worker   // For new virtual methods that don't override.
589*795d594fSAndroid Build Coastguard Worker   for (int32_t i = super_class->GetVTableLength(); i < klass->GetVTableLength(); ++i) {
590*795d594fSAndroid Build Coastguard Worker     ArtMethod* method = klass->GetVTableEntry(i, image_pointer_size);
591*795d594fSAndroid Build Coastguard Worker     InitSingleImplementationFlag(klass, method, image_pointer_size);
592*795d594fSAndroid Build Coastguard Worker   }
593*795d594fSAndroid Build Coastguard Worker 
594*795d594fSAndroid Build Coastguard Worker   if (klass->IsInstantiable()) {
595*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::IfTable> iftable = klass->GetIfTable();
596*795d594fSAndroid Build Coastguard Worker     const size_t ifcount = klass->GetIfTableCount();
597*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0; i < ifcount; ++i) {
598*795d594fSAndroid Build Coastguard Worker       ObjPtr<mirror::Class> interface = iftable->GetInterface(i);
599*795d594fSAndroid Build Coastguard Worker       for (size_t j = 0, count = iftable->GetMethodArrayCount(i); j < count; ++j) {
600*795d594fSAndroid Build Coastguard Worker         ArtMethod* interface_method = interface->GetVirtualMethod(j, image_pointer_size);
601*795d594fSAndroid Build Coastguard Worker         ObjPtr<mirror::PointerArray> method_array = iftable->GetMethodArray(i);
602*795d594fSAndroid Build Coastguard Worker         ArtMethod* implementation_method =
603*795d594fSAndroid Build Coastguard Worker             method_array->GetElementPtrSize<ArtMethod*>(j, image_pointer_size);
604*795d594fSAndroid Build Coastguard Worker         DCHECK(implementation_method != nullptr) << klass->PrettyClass();
605*795d594fSAndroid Build Coastguard Worker         CheckInterfaceMethodSingleImplementationInfo(klass,
606*795d594fSAndroid Build Coastguard Worker                                                      interface_method,
607*795d594fSAndroid Build Coastguard Worker                                                      implementation_method,
608*795d594fSAndroid Build Coastguard Worker                                                      invalidated_single_impl_methods,
609*795d594fSAndroid Build Coastguard Worker                                                      image_pointer_size);
610*795d594fSAndroid Build Coastguard Worker       }
611*795d594fSAndroid Build Coastguard Worker     }
612*795d594fSAndroid Build Coastguard Worker   }
613*795d594fSAndroid Build Coastguard Worker 
614*795d594fSAndroid Build Coastguard Worker   InvalidateSingleImplementationMethods(invalidated_single_impl_methods);
615*795d594fSAndroid Build Coastguard Worker }
616*795d594fSAndroid Build Coastguard Worker 
InvalidateSingleImplementationMethods(std::unordered_set<ArtMethod * > & invalidated_single_impl_methods)617*795d594fSAndroid Build Coastguard Worker void ClassHierarchyAnalysis::InvalidateSingleImplementationMethods(
618*795d594fSAndroid Build Coastguard Worker     std::unordered_set<ArtMethod*>& invalidated_single_impl_methods) {
619*795d594fSAndroid Build Coastguard Worker   if (!invalidated_single_impl_methods.empty()) {
620*795d594fSAndroid Build Coastguard Worker     Runtime* const runtime = Runtime::Current();
621*795d594fSAndroid Build Coastguard Worker     Thread *self = Thread::Current();
622*795d594fSAndroid Build Coastguard Worker     // Method headers for compiled code to be invalidated.
623*795d594fSAndroid Build Coastguard Worker     std::unordered_set<OatQuickMethodHeader*> dependent_method_headers;
624*795d594fSAndroid Build Coastguard Worker     PointerSize image_pointer_size =
625*795d594fSAndroid Build Coastguard Worker         Runtime::Current()->GetClassLinker()->GetImagePointerSize();
626*795d594fSAndroid Build Coastguard Worker 
627*795d594fSAndroid Build Coastguard Worker     {
628*795d594fSAndroid Build Coastguard Worker       // We do this under cha_lock_. Committing code also grabs this lock to
629*795d594fSAndroid Build Coastguard Worker       // make sure the code is only committed when all single-implementation
630*795d594fSAndroid Build Coastguard Worker       // assumptions are still true.
631*795d594fSAndroid Build Coastguard Worker       std::vector<std::pair<ArtMethod*, OatQuickMethodHeader*>> headers;
632*795d594fSAndroid Build Coastguard Worker       {
633*795d594fSAndroid Build Coastguard Worker         MutexLock cha_mu(self, *Locks::cha_lock_);
634*795d594fSAndroid Build Coastguard Worker         // Invalidate compiled methods that assume some virtual calls have only
635*795d594fSAndroid Build Coastguard Worker         // single implementations.
636*795d594fSAndroid Build Coastguard Worker         for (ArtMethod* invalidated : invalidated_single_impl_methods) {
637*795d594fSAndroid Build Coastguard Worker           if (!invalidated->HasSingleImplementation()) {
638*795d594fSAndroid Build Coastguard Worker             // It might have been invalidated already when other class linking is
639*795d594fSAndroid Build Coastguard Worker             // going on.
640*795d594fSAndroid Build Coastguard Worker             continue;
641*795d594fSAndroid Build Coastguard Worker           }
642*795d594fSAndroid Build Coastguard Worker           invalidated->SetHasSingleImplementation(false);
643*795d594fSAndroid Build Coastguard Worker           if (invalidated->IsAbstract()) {
644*795d594fSAndroid Build Coastguard Worker             // Clear the single implementation method.
645*795d594fSAndroid Build Coastguard Worker             invalidated->SetSingleImplementation(nullptr, image_pointer_size);
646*795d594fSAndroid Build Coastguard Worker           }
647*795d594fSAndroid Build Coastguard Worker 
648*795d594fSAndroid Build Coastguard Worker           if (runtime->IsAotCompiler()) {
649*795d594fSAndroid Build Coastguard Worker             // No need to invalidate any compiled code as the AotCompiler doesn't
650*795d594fSAndroid Build Coastguard Worker             // run any code.
651*795d594fSAndroid Build Coastguard Worker             continue;
652*795d594fSAndroid Build Coastguard Worker           }
653*795d594fSAndroid Build Coastguard Worker 
654*795d594fSAndroid Build Coastguard Worker           // Invalidate all dependents.
655*795d594fSAndroid Build Coastguard Worker           for (const auto& dependent : GetDependents(invalidated)) {
656*795d594fSAndroid Build Coastguard Worker             ArtMethod* method = dependent.first;;
657*795d594fSAndroid Build Coastguard Worker             OatQuickMethodHeader* method_header = dependent.second;
658*795d594fSAndroid Build Coastguard Worker             VLOG(class_linker) << "CHA invalidated compiled code for " << method->PrettyMethod();
659*795d594fSAndroid Build Coastguard Worker             DCHECK(runtime->UseJitCompilation());
660*795d594fSAndroid Build Coastguard Worker             // We need to call JitCodeCache::InvalidateCompiledCodeFor but we cannot do it here
661*795d594fSAndroid Build Coastguard Worker             // since it would run into problems with lock-ordering. We don't want to re-order the
662*795d594fSAndroid Build Coastguard Worker             // locks since that would make code-commit racy.
663*795d594fSAndroid Build Coastguard Worker             headers.push_back({method, method_header});
664*795d594fSAndroid Build Coastguard Worker             dependent_method_headers.insert(method_header);
665*795d594fSAndroid Build Coastguard Worker           }
666*795d594fSAndroid Build Coastguard Worker           RemoveAllDependenciesFor(invalidated);
667*795d594fSAndroid Build Coastguard Worker         }
668*795d594fSAndroid Build Coastguard Worker       }
669*795d594fSAndroid Build Coastguard Worker       // Since we are still loading the class that invalidated the code it's fine we have this after
670*795d594fSAndroid Build Coastguard Worker       // getting rid of the dependency. Any calls would need to be with the old version (since the
671*795d594fSAndroid Build Coastguard Worker       // new one isn't loaded yet) which still works fine. We will deoptimize just after this to
672*795d594fSAndroid Build Coastguard Worker       // ensure everything gets the new state.
673*795d594fSAndroid Build Coastguard Worker       jit::Jit* jit = Runtime::Current()->GetJit();
674*795d594fSAndroid Build Coastguard Worker       if (jit != nullptr) {
675*795d594fSAndroid Build Coastguard Worker         jit::JitCodeCache* code_cache = jit->GetCodeCache();
676*795d594fSAndroid Build Coastguard Worker         for (const auto& pair : headers) {
677*795d594fSAndroid Build Coastguard Worker           code_cache->InvalidateCompiledCodeFor(pair.first, pair.second);
678*795d594fSAndroid Build Coastguard Worker         }
679*795d594fSAndroid Build Coastguard Worker       }
680*795d594fSAndroid Build Coastguard Worker     }
681*795d594fSAndroid Build Coastguard Worker 
682*795d594fSAndroid Build Coastguard Worker     if (dependent_method_headers.empty()) {
683*795d594fSAndroid Build Coastguard Worker       return;
684*795d594fSAndroid Build Coastguard Worker     }
685*795d594fSAndroid Build Coastguard Worker     // Deoptimze compiled code on stack that should have been invalidated.
686*795d594fSAndroid Build Coastguard Worker     CHACheckpoint checkpoint(dependent_method_headers);
687*795d594fSAndroid Build Coastguard Worker     size_t threads_running_checkpoint = runtime->GetThreadList()->RunCheckpoint(&checkpoint);
688*795d594fSAndroid Build Coastguard Worker     if (threads_running_checkpoint != 0) {
689*795d594fSAndroid Build Coastguard Worker       checkpoint.WaitForThreadsToRunThroughCheckpoint(threads_running_checkpoint);
690*795d594fSAndroid Build Coastguard Worker     }
691*795d594fSAndroid Build Coastguard Worker   }
692*795d594fSAndroid Build Coastguard Worker }
693*795d594fSAndroid Build Coastguard Worker 
RemoveDependenciesForLinearAlloc(Thread * self,const LinearAlloc * linear_alloc)694*795d594fSAndroid Build Coastguard Worker void ClassHierarchyAnalysis::RemoveDependenciesForLinearAlloc(Thread* self,
695*795d594fSAndroid Build Coastguard Worker                                                               const LinearAlloc* linear_alloc) {
696*795d594fSAndroid Build Coastguard Worker   MutexLock mu(self, *Locks::cha_lock_);
697*795d594fSAndroid Build Coastguard Worker   for (auto it = cha_dependency_map_.begin(); it != cha_dependency_map_.end(); ) {
698*795d594fSAndroid Build Coastguard Worker     // Use unsafe to avoid locking since the allocator is going to be deleted.
699*795d594fSAndroid Build Coastguard Worker     if (linear_alloc->ContainsUnsafe(it->first)) {
700*795d594fSAndroid Build Coastguard Worker       // About to delete the ArtMethod, erase the entry from the map.
701*795d594fSAndroid Build Coastguard Worker       it = cha_dependency_map_.erase(it);
702*795d594fSAndroid Build Coastguard Worker     } else {
703*795d594fSAndroid Build Coastguard Worker       ++it;
704*795d594fSAndroid Build Coastguard Worker     }
705*795d594fSAndroid Build Coastguard Worker   }
706*795d594fSAndroid Build Coastguard Worker }
707*795d594fSAndroid Build Coastguard Worker 
708*795d594fSAndroid Build Coastguard Worker }  // namespace art
709