blob: d19d4f6e3029a8cdf43b2121374e81969d0f6f36 [file] [log] [blame]
Mingyao Yang063fc772016-08-02 11:02:54 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "cha.h"
18
Andreas Gampe90b936d2017-01-31 08:58:55 -080019#include "art_method-inl.h"
Andreas Gampe170331f2017-12-07 18:41:03 -080020#include "base/logging.h" // For VLOG
Andreas Gampe7fbc4a52018-11-28 08:26:47 -080021#include "base/mutex.h"
Mingyao Yang063fc772016-08-02 11:02:54 -070022#include "jit/jit.h"
23#include "jit/jit_code_cache.h"
Mathieu Chartiercf79cf52017-07-21 11:17:57 -070024#include "linear_alloc.h"
Alexey Grebenkinbe4c2bd2018-02-01 19:09:59 +030025#include "mirror/class_loader.h"
Mingyao Yang063fc772016-08-02 11:02:54 -070026#include "runtime.h"
27#include "scoped_thread_state_change-inl.h"
28#include "stack.h"
29#include "thread.h"
30#include "thread_list.h"
31#include "thread_pool.h"
32
33namespace art {
34
35void ClassHierarchyAnalysis::AddDependency(ArtMethod* method,
36 ArtMethod* dependent_method,
37 OatQuickMethodHeader* dependent_header) {
Mingyao Yangcc104502017-05-24 17:13:03 -070038 const auto it = cha_dependency_map_.insert(
39 decltype(cha_dependency_map_)::value_type(method, ListOfDependentPairs())).first;
40 it->second.push_back({dependent_method, dependent_header});
Mingyao Yang063fc772016-08-02 11:02:54 -070041}
42
Mingyao Yangcc104502017-05-24 17:13:03 -070043static const ClassHierarchyAnalysis::ListOfDependentPairs s_empty_vector;
44
45const ClassHierarchyAnalysis::ListOfDependentPairs& ClassHierarchyAnalysis::GetDependents(
46 ArtMethod* method) {
Mingyao Yang063fc772016-08-02 11:02:54 -070047 auto it = cha_dependency_map_.find(method);
48 if (it != cha_dependency_map_.end()) {
Mingyao Yang063fc772016-08-02 11:02:54 -070049 return it->second;
50 }
Mingyao Yangcc104502017-05-24 17:13:03 -070051 return s_empty_vector;
Mingyao Yang063fc772016-08-02 11:02:54 -070052}
53
Mingyao Yangcc104502017-05-24 17:13:03 -070054void ClassHierarchyAnalysis::RemoveAllDependenciesFor(ArtMethod* method) {
55 cha_dependency_map_.erase(method);
Mingyao Yang063fc772016-08-02 11:02:54 -070056}
57
58void ClassHierarchyAnalysis::RemoveDependentsWithMethodHeaders(
59 const std::unordered_set<OatQuickMethodHeader*>& method_headers) {
60 // Iterate through all entries in the dependency map and remove any entry that
61 // contains one of those in method_headers.
62 for (auto map_it = cha_dependency_map_.begin(); map_it != cha_dependency_map_.end(); ) {
Mingyao Yangcc104502017-05-24 17:13:03 -070063 ListOfDependentPairs& dependents = map_it->second;
64 dependents.erase(
65 std::remove_if(
66 dependents.begin(),
67 dependents.end(),
68 [&method_headers](MethodAndMethodHeaderPair& dependent) {
69 return method_headers.find(dependent.second) != method_headers.end();
70 }),
71 dependents.end());
72
Mingyao Yang063fc772016-08-02 11:02:54 -070073 // Remove the map entry if there are no more dependents.
Mingyao Yangcc104502017-05-24 17:13:03 -070074 if (dependents.empty()) {
Mingyao Yang063fc772016-08-02 11:02:54 -070075 map_it = cha_dependency_map_.erase(map_it);
Mingyao Yang063fc772016-08-02 11:02:54 -070076 } else {
77 map_it++;
78 }
79 }
80}
81
Alexey Grebenkinbe4c2bd2018-02-01 19:09:59 +030082void ClassHierarchyAnalysis::ResetSingleImplementationInHierarchy(ObjPtr<mirror::Class> klass,
83 const LinearAlloc* alloc,
84 const PointerSize pointer_size)
85 const {
86 // Presumably called from some sort of class visitor, no null pointers expected.
87 DCHECK(klass != nullptr);
88 DCHECK(alloc != nullptr);
89
90 // Skip interfaces since they cannot provide SingleImplementations to work with.
91 if (klass->IsInterface()) {
92 return;
93 }
94
95 // This method is called while visiting classes in the class table of a class loader.
96 // That means, some 'klass'es can belong to other classloaders. Argument 'alloc'
97 // allows to explicitly indicate a classloader, which is going to be deleted.
98 // Filter out classes, that do not belong to it.
99 if (!alloc->ContainsUnsafe(klass->GetMethodsPtr())) {
100 return;
101 }
102
103 // CHA analysis is only applied to resolved classes.
104 if (!klass->IsResolved()) {
105 return;
106 }
107
108 ObjPtr<mirror::Class> super = klass->GetSuperClass<kDefaultVerifyFlags, kWithoutReadBarrier>();
109
110 // Skip Object class and primitive classes.
111 if (super == nullptr) {
112 return;
113 }
114
115 // The class is going to be deleted. Iterate over the virtual methods of its superclasses to see
116 // if they have SingleImplementations methods defined by 'klass'.
117 // Skip all virtual methods that do not override methods from super class since they cannot be
118 // SingleImplementations for anything.
Vladimir Markodbcb48f2018-11-12 11:47:04 +0000119 int32_t vtbl_size = super->GetVTableLength<kDefaultVerifyFlags>();
Alexey Grebenkinbe4c2bd2018-02-01 19:09:59 +0300120 ObjPtr<mirror::ClassLoader> loader =
121 klass->GetClassLoader<kDefaultVerifyFlags, kWithoutReadBarrier>();
122 for (int vtbl_index = 0; vtbl_index < vtbl_size; ++vtbl_index) {
123 ArtMethod* method =
124 klass->GetVTableEntry<kDefaultVerifyFlags, kWithoutReadBarrier>(vtbl_index, pointer_size);
125 if (!alloc->ContainsUnsafe(method)) {
126 continue;
127 }
128
129 // Find all occurrences of virtual methods in parents' SingleImplementations fields
130 // and reset them.
131 // No need to reset SingleImplementations for the method itself (it will be cleared anyways),
132 // so start with a superclass and move up looking into a corresponding vtbl slot.
133 for (ObjPtr<mirror::Class> super_it = super;
134 super_it != nullptr &&
Vladimir Markodbcb48f2018-11-12 11:47:04 +0000135 super_it->GetVTableLength<kDefaultVerifyFlags>() > vtbl_index;
Alexey Grebenkinbe4c2bd2018-02-01 19:09:59 +0300136 super_it = super_it->GetSuperClass<kDefaultVerifyFlags, kWithoutReadBarrier>()) {
137 // Skip superclasses that are also going to be unloaded.
138 ObjPtr<mirror::ClassLoader> super_loader = super_it->
139 GetClassLoader<kDefaultVerifyFlags, kWithoutReadBarrier>();
140 if (super_loader == loader) {
141 continue;
142 }
143
144 ArtMethod* super_method = super_it->
145 GetVTableEntry<kDefaultVerifyFlags, kWithoutReadBarrier>(vtbl_index, pointer_size);
Vladimir Markoc945e0d2018-07-18 17:26:45 +0100146 if (super_method->IsAbstract() &&
Alexey Grebenkinbe4c2bd2018-02-01 19:09:59 +0300147 super_method->HasSingleImplementation<kWithoutReadBarrier>() &&
Vladimir Markoc945e0d2018-07-18 17:26:45 +0100148 super_method->GetSingleImplementation(pointer_size) == method) {
Alexey Grebenkinbe4c2bd2018-02-01 19:09:59 +0300149 // Do like there was no single implementation defined previously
150 // for this method of the superclass.
Vladimir Markoc945e0d2018-07-18 17:26:45 +0100151 super_method->SetSingleImplementation(nullptr, pointer_size);
Alexey Grebenkinbe4c2bd2018-02-01 19:09:59 +0300152 } else {
153 // No related SingleImplementations could possibly be found any further.
154 DCHECK(!super_method->HasSingleImplementation<kWithoutReadBarrier>());
155 break;
156 }
157 }
158 }
159
160 // Check all possible interface methods too.
161 ObjPtr<mirror::IfTable> iftable = klass->GetIfTable<kDefaultVerifyFlags, kWithoutReadBarrier>();
Vladimir Markodbcb48f2018-11-12 11:47:04 +0000162 const size_t ifcount = klass->GetIfTableCount<kDefaultVerifyFlags>();
Alexey Grebenkinbe4c2bd2018-02-01 19:09:59 +0300163 for (size_t i = 0; i < ifcount; ++i) {
164 ObjPtr<mirror::Class> interface =
165 iftable->GetInterface<kDefaultVerifyFlags, kWithoutReadBarrier>(i);
166 for (size_t j = 0,
167 count = iftable->GetMethodArrayCount<kDefaultVerifyFlags, kWithoutReadBarrier>(i);
168 j < count;
169 ++j) {
170 ArtMethod* method = interface->GetVirtualMethod(j, pointer_size);
171 if (method->HasSingleImplementation<kWithoutReadBarrier>() &&
Vladimir Markoc945e0d2018-07-18 17:26:45 +0100172 alloc->ContainsUnsafe(method->GetSingleImplementation(pointer_size)) &&
173 !method->IsDefault()) {
Alexey Grebenkinbe4c2bd2018-02-01 19:09:59 +0300174 // Do like there was no single implementation defined previously for this method.
Vladimir Markoc945e0d2018-07-18 17:26:45 +0100175 method->SetSingleImplementation(nullptr, pointer_size);
Alexey Grebenkinbe4c2bd2018-02-01 19:09:59 +0300176 }
177 }
178 }
179}
180
Mingyao Yang063fc772016-08-02 11:02:54 -0700181// This stack visitor walks the stack and for compiled code with certain method
182// headers, sets the should_deoptimize flag on stack to 1.
183// TODO: also set the register value to 1 when should_deoptimize is allocated in
184// a register.
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100185class CHAStackVisitor final : public StackVisitor {
Mingyao Yang063fc772016-08-02 11:02:54 -0700186 public:
187 CHAStackVisitor(Thread* thread_in,
188 Context* context,
189 const std::unordered_set<OatQuickMethodHeader*>& method_headers)
190 : StackVisitor(thread_in, context, StackVisitor::StackWalkKind::kSkipInlinedFrames),
191 method_headers_(method_headers) {
192 }
193
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100194 bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) {
Mingyao Yang063fc772016-08-02 11:02:54 -0700195 ArtMethod* method = GetMethod();
Mingyao Yang7b9a83f2016-12-13 12:28:31 -0800196 // Avoid types of methods that do not have an oat quick method header.
197 if (method == nullptr ||
198 method->IsRuntimeMethod() ||
199 method->IsNative() ||
200 method->IsProxyMethod()) {
Mingyao Yang063fc772016-08-02 11:02:54 -0700201 return true;
202 }
203 if (GetCurrentQuickFrame() == nullptr) {
204 // Not compiled code.
205 return true;
206 }
207 // Method may have multiple versions of compiled code. Check
208 // the method header to see if it has should_deoptimize flag.
209 const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
Mingyao Yang7b9a83f2016-12-13 12:28:31 -0800210 DCHECK(method_header != nullptr);
Mingyao Yang063fc772016-08-02 11:02:54 -0700211 if (!method_header->HasShouldDeoptimizeFlag()) {
212 // This compiled version doesn't have should_deoptimize flag. Skip.
213 return true;
214 }
215 auto it = std::find(method_headers_.begin(), method_headers_.end(), method_header);
216 if (it == method_headers_.end()) {
217 // Not in the list of method headers that should be deoptimized.
218 return true;
219 }
220
221 // The compiled code on stack is not valid anymore. Need to deoptimize.
Mythri Alle5097f832021-11-02 14:52:30 +0000222 SetShouldDeoptimizeFlag(DeoptimizeFlagValue::kCHA);
Mingyao Yang063fc772016-08-02 11:02:54 -0700223
224 return true;
225 }
226
227 private:
Mingyao Yang063fc772016-08-02 11:02:54 -0700228 // Set of method headers for compiled code that should be deoptimized.
229 const std::unordered_set<OatQuickMethodHeader*>& method_headers_;
230
231 DISALLOW_COPY_AND_ASSIGN(CHAStackVisitor);
232};
233
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100234class CHACheckpoint final : public Closure {
Mingyao Yang063fc772016-08-02 11:02:54 -0700235 public:
236 explicit CHACheckpoint(const std::unordered_set<OatQuickMethodHeader*>& method_headers)
237 : barrier_(0),
238 method_headers_(method_headers) {}
239
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100240 void Run(Thread* thread) override {
Mingyao Yang063fc772016-08-02 11:02:54 -0700241 // Note thread and self may not be equal if thread was already suspended at
242 // the point of the request.
243 Thread* self = Thread::Current();
244 ScopedObjectAccess soa(self);
245 CHAStackVisitor visitor(thread, nullptr, method_headers_);
246 visitor.WalkStack();
247 barrier_.Pass(self);
248 }
249
250 void WaitForThreadsToRunThroughCheckpoint(size_t threads_running_checkpoint) {
251 Thread* self = Thread::Current();
Vladimir Markoddf4fd32021-11-22 16:31:57 +0000252 ScopedThreadStateChange tsc(self, ThreadState::kWaitingForCheckPointsToRun);
Mingyao Yang063fc772016-08-02 11:02:54 -0700253 barrier_.Increment(self, threads_running_checkpoint);
254 }
255
256 private:
257 // The barrier to be passed through and for the requestor to wait upon.
258 Barrier barrier_;
259 // List of method headers for invalidated compiled code.
260 const std::unordered_set<OatQuickMethodHeader*>& method_headers_;
261
262 DISALLOW_COPY_AND_ASSIGN(CHACheckpoint);
263};
264
Andreas Gampe582d96a2017-07-24 13:51:47 -0700265
Andreas Gampe98104992018-10-16 12:49:47 -0700266static void VerifyNonSingleImplementation(ObjPtr<mirror::Class> verify_class,
Andreas Gampe582d96a2017-07-24 13:51:47 -0700267 uint16_t verify_index,
268 ArtMethod* excluded_method)
269 REQUIRES_SHARED(Locks::mutator_lock_) {
270 if (!kIsDebugBuild) {
271 return;
272 }
273
Mingyao Yang063fc772016-08-02 11:02:54 -0700274 // Grab cha_lock_ to make sure all single-implementation updates are seen.
Andreas Gampe582d96a2017-07-24 13:51:47 -0700275 MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
276
Mingyao Yang063fc772016-08-02 11:02:54 -0700277 PointerSize image_pointer_size =
278 Runtime::Current()->GetClassLinker()->GetImagePointerSize();
Andreas Gampe582d96a2017-07-24 13:51:47 -0700279
Andreas Gampe98104992018-10-16 12:49:47 -0700280 ObjPtr<mirror::Class> input_verify_class = verify_class;
Andreas Gampe582d96a2017-07-24 13:51:47 -0700281
Mingyao Yang063fc772016-08-02 11:02:54 -0700282 while (verify_class != nullptr) {
283 if (verify_index >= verify_class->GetVTableLength()) {
284 return;
285 }
286 ArtMethod* verify_method = verify_class->GetVTableEntry(verify_index, image_pointer_size);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800287 if (verify_method != excluded_method) {
Andreas Gampe98104992018-10-16 12:49:47 -0700288 auto construct_parent_chain = [](ObjPtr<mirror::Class> failed, ObjPtr<mirror::Class> in)
Andreas Gampe582d96a2017-07-24 13:51:47 -0700289 REQUIRES_SHARED(Locks::mutator_lock_) {
290 std::string tmp = in->PrettyClass();
291 while (in != failed) {
292 in = in->GetSuperClass();
293 tmp = tmp + "->" + in->PrettyClass();
294 }
295 return tmp;
296 };
Mingyao Yange8fcd012017-01-20 10:43:30 -0800297 DCHECK(!verify_method->HasSingleImplementation())
298 << "class: " << verify_class->PrettyClass()
Mingyao Yang37c8e5c2017-02-10 11:25:05 -0800299 << " verify_method: " << verify_method->PrettyMethod(true)
Andreas Gampe582d96a2017-07-24 13:51:47 -0700300 << " (" << construct_parent_chain(verify_class, input_verify_class) << ")"
301 << " excluded_method: " << ArtMethod::PrettyMethod(excluded_method);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800302 if (verify_method->IsAbstract()) {
303 DCHECK(verify_method->GetSingleImplementation(image_pointer_size) == nullptr);
304 }
305 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700306 verify_class = verify_class->GetSuperClass();
307 }
308}
309
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000310void ClassHierarchyAnalysis::CheckVirtualMethodSingleImplementationInfo(
Mingyao Yang063fc772016-08-02 11:02:54 -0700311 Handle<mirror::Class> klass,
312 ArtMethod* virtual_method,
313 ArtMethod* method_in_super,
Mingyao Yange8fcd012017-01-20 10:43:30 -0800314 std::unordered_set<ArtMethod*>& invalidated_single_impl_methods,
315 PointerSize pointer_size) {
Mingyao Yang063fc772016-08-02 11:02:54 -0700316 // TODO: if klass is not instantiable, virtual_method isn't invocable yet so
317 // even if it overrides, it doesn't invalidate single-implementation
318 // assumption.
319
Santiago Aboy Solanes6cdabe12022-02-18 15:27:43 +0000320 DCHECK_IMPLIES(virtual_method == method_in_super, virtual_method->IsAbstract());
Mingyao Yang063fc772016-08-02 11:02:54 -0700321 DCHECK(method_in_super->GetDeclaringClass()->IsResolved()) << "class isn't resolved";
322 // If virtual_method doesn't come from a default interface method, it should
323 // be supplied by klass.
Mingyao Yange8fcd012017-01-20 10:43:30 -0800324 DCHECK(virtual_method == method_in_super ||
325 virtual_method->IsCopied() ||
Mingyao Yang063fc772016-08-02 11:02:54 -0700326 virtual_method->GetDeclaringClass() == klass.Get());
327
Mingyao Yange8fcd012017-01-20 10:43:30 -0800328 // To make updating single-implementation flags simple, we always maintain the following
329 // invariant:
330 // Say all virtual methods in the same vtable slot, starting from the bottom child class
331 // to super classes, is a sequence of unique methods m3, m2, m1, ... (after removing duplicate
332 // methods for inherited methods).
333 // For example for the following class hierarchy,
334 // class A { void m() { ... } }
335 // class B extends A { void m() { ... } }
336 // class C extends B {}
337 // class D extends C { void m() { ... } }
338 // the sequence is D.m(), B.m(), A.m().
339 // The single-implementation status for that sequence of methods begin with one or two true's,
340 // then become all falses. The only case where two true's are possible is for one abstract
341 // method m and one non-abstract method mImpl that overrides method m.
342 // With the invariant, when linking in a new class, we only need to at most update one or
343 // two methods in the sequence for their single-implementation status, in order to maintain
344 // the invariant.
345
Mingyao Yang063fc772016-08-02 11:02:54 -0700346 if (!method_in_super->HasSingleImplementation()) {
347 // method_in_super already has multiple implementations. All methods in the
348 // same vtable slots in its super classes should have
349 // non-single-implementation already.
Andreas Gampe582d96a2017-07-24 13:51:47 -0700350 VerifyNonSingleImplementation(klass->GetSuperClass()->GetSuperClass(),
351 method_in_super->GetMethodIndex(),
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700352 /* excluded_method= */ nullptr);
Mingyao Yang063fc772016-08-02 11:02:54 -0700353 return;
354 }
355
Mingyao Yange8fcd012017-01-20 10:43:30 -0800356 uint16_t method_index = method_in_super->GetMethodIndex();
357 if (method_in_super->IsAbstract()) {
Andreas Gampe582d96a2017-07-24 13:51:47 -0700358 // An abstract method should have made all methods in the same vtable
359 // slot above it in the class hierarchy having non-single-implementation.
360 VerifyNonSingleImplementation(klass->GetSuperClass()->GetSuperClass(),
361 method_index,
362 method_in_super);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800363
364 if (virtual_method->IsAbstract()) {
365 // SUPER: abstract, VIRTUAL: abstract.
366 if (method_in_super == virtual_method) {
367 DCHECK(klass->IsInstantiable());
368 // An instantiable subclass hasn't provided a concrete implementation of
369 // the abstract method. Invoking method_in_super may throw AbstractMethodError.
370 // This is an uncommon case, so we simply treat method_in_super as not
371 // having single-implementation.
372 invalidated_single_impl_methods.insert(method_in_super);
373 return;
374 } else {
375 // One abstract method overrides another abstract method. This is an uncommon
376 // case. We simply treat method_in_super as not having single-implementation.
377 invalidated_single_impl_methods.insert(method_in_super);
378 return;
379 }
380 } else {
381 // SUPER: abstract, VIRTUAL: non-abstract.
382 // A non-abstract method overrides an abstract method.
Vladimir Marko525c2b52022-01-31 12:54:29 +0000383 if (!virtual_method->IsDefaultConflicting() &&
384 method_in_super->GetSingleImplementation(pointer_size) == nullptr) {
Mingyao Yange8fcd012017-01-20 10:43:30 -0800385 // Abstract method_in_super has no implementation yet.
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000386 // We need to grab cha_lock_ since there may be multiple class linking
387 // going on that can check/modify the single-implementation flag/method
388 // of method_in_super.
Mingyao Yange8fcd012017-01-20 10:43:30 -0800389 MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
390 if (!method_in_super->HasSingleImplementation()) {
391 return;
392 }
393 if (method_in_super->GetSingleImplementation(pointer_size) == nullptr) {
394 // virtual_method becomes the first implementation for method_in_super.
395 method_in_super->SetSingleImplementation(virtual_method, pointer_size);
396 // Keep method_in_super's single-implementation status.
397 return;
398 }
399 // Fall through to invalidate method_in_super's single-implementation status.
400 }
401 // Abstract method_in_super already got one implementation.
402 // Invalidate method_in_super's single-implementation status.
403 invalidated_single_impl_methods.insert(method_in_super);
404 return;
405 }
406 } else {
407 if (virtual_method->IsAbstract()) {
408 // SUPER: non-abstract, VIRTUAL: abstract.
409 // An abstract method overrides a non-abstract method. This is an uncommon
410 // case, we simply treat both methods as not having single-implementation.
411 invalidated_single_impl_methods.insert(virtual_method);
412 // Fall-through to handle invalidating method_in_super of its
413 // single-implementation status.
414 }
415
416 // SUPER: non-abstract, VIRTUAL: non-abstract/abstract(fall-through from previous if).
417 // Invalidate method_in_super's single-implementation status.
418 invalidated_single_impl_methods.insert(method_in_super);
419
420 // method_in_super might be the single-implementation of another abstract method,
421 // which should be also invalidated of its single-implementation status.
Andreas Gampe98104992018-10-16 12:49:47 -0700422 ObjPtr<mirror::Class> super_super = klass->GetSuperClass()->GetSuperClass();
Mingyao Yange8fcd012017-01-20 10:43:30 -0800423 while (super_super != nullptr &&
424 method_index < super_super->GetVTableLength()) {
425 ArtMethod* method_in_super_super = super_super->GetVTableEntry(method_index, pointer_size);
426 if (method_in_super_super != method_in_super) {
427 if (method_in_super_super->IsAbstract()) {
428 if (method_in_super_super->HasSingleImplementation()) {
429 // Invalidate method_in_super's single-implementation status.
430 invalidated_single_impl_methods.insert(method_in_super_super);
431 // No need to further traverse up the class hierarchy since if there
432 // are cases that one abstract method overrides another method, we
433 // should have made that method having non-single-implementation already.
434 } else {
435 // method_in_super_super is already non-single-implementation.
436 // No need to further traverse up the class hierarchy.
437 }
438 } else {
439 DCHECK(!method_in_super_super->HasSingleImplementation());
440 // No need to further traverse up the class hierarchy since two non-abstract
441 // methods (method_in_super and method_in_super_super) should have set all
442 // other methods (abstract or not) in the vtable slot to be non-single-implementation.
443 }
444
Andreas Gampe582d96a2017-07-24 13:51:47 -0700445 VerifyNonSingleImplementation(super_super->GetSuperClass(),
446 method_index,
447 method_in_super_super);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800448 // No need to go any further.
449 return;
450 } else {
451 super_super = super_super->GetSuperClass();
452 }
453 }
454 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700455}
456
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000457void ClassHierarchyAnalysis::CheckInterfaceMethodSingleImplementationInfo(
458 Handle<mirror::Class> klass,
459 ArtMethod* interface_method,
460 ArtMethod* implementation_method,
461 std::unordered_set<ArtMethod*>& invalidated_single_impl_methods,
462 PointerSize pointer_size) {
463 DCHECK(klass->IsInstantiable());
464 DCHECK(interface_method->IsAbstract() || interface_method->IsDefault());
465
466 if (!interface_method->HasSingleImplementation()) {
467 return;
468 }
469
Vladimir Markoc2262112022-02-02 12:25:57 +0000470 if (!implementation_method->IsInvokable()) {
471 DCHECK(implementation_method->IsAbstract() || implementation_method->IsDefaultConflicting());
472 // An instantiable class doesn't supply an implementation for interface_method,
473 // or has conflicting default method implementations. Invoking the interface method
474 // on the class will throw AbstractMethodError or IncompatibleClassChangeError.
475 // (Note: The RI throws AME instead of ICCE for default conflict.) This is an uncommon
476 // case, so we simply treat interface_method as not having single-implementation.
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000477 invalidated_single_impl_methods.insert(interface_method);
478 return;
479 }
480
481 // We need to grab cha_lock_ since there may be multiple class linking going
482 // on that can check/modify the single-implementation flag/method of
483 // interface_method.
484 MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
485 // Do this check again after we grab cha_lock_.
486 if (!interface_method->HasSingleImplementation()) {
487 return;
488 }
489
490 ArtMethod* single_impl = interface_method->GetSingleImplementation(pointer_size);
491 if (single_impl == nullptr) {
492 // implementation_method becomes the first implementation for
493 // interface_method.
494 interface_method->SetSingleImplementation(implementation_method, pointer_size);
495 // Keep interface_method's single-implementation status.
496 return;
497 }
Vladimir Markoc2262112022-02-02 12:25:57 +0000498 DCHECK(single_impl->IsInvokable());
499 if ((single_impl->GetDeclaringClass() == implementation_method->GetDeclaringClass())) {
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000500 // Same implementation. Since implementation_method may be a copy of a default
501 // method, we need to check the declaring class for equality.
502 return;
503 }
504 // Another implementation for interface_method.
505 invalidated_single_impl_methods.insert(interface_method);
506}
507
Mingyao Yang063fc772016-08-02 11:02:54 -0700508void ClassHierarchyAnalysis::InitSingleImplementationFlag(Handle<mirror::Class> klass,
Mingyao Yange8fcd012017-01-20 10:43:30 -0800509 ArtMethod* method,
510 PointerSize pointer_size) {
Mingyao Yang063fc772016-08-02 11:02:54 -0700511 DCHECK(method->IsCopied() || method->GetDeclaringClass() == klass.Get());
512 if (klass->IsFinal() || method->IsFinal()) {
513 // Final classes or methods do not need CHA for devirtualization.
514 // This frees up modifier bits for intrinsics which currently are only
515 // used for static methods or methods of final classes.
516 return;
517 }
Mingyao Yang37c8e5c2017-02-10 11:25:05 -0800518 if (method->IsAbstract()) {
519 // single-implementation of abstract method shares the same field
520 // that's used for JNI function of native method. It's fine since a method
521 // cannot be both abstract and native.
522 DCHECK(!method->IsNative()) << "Abstract method cannot be native";
523
Mingyao Yange8fcd012017-01-20 10:43:30 -0800524 if (method->GetDeclaringClass()->IsInstantiable()) {
525 // Rare case, but we do accept it (such as 800-smali/smali/b_26143249.smali).
526 // Do not attempt to devirtualize it.
527 method->SetHasSingleImplementation(false);
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000528 DCHECK(method->GetSingleImplementation(pointer_size) == nullptr);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800529 } else {
530 // Abstract method starts with single-implementation flag set and null
531 // implementation method.
532 method->SetHasSingleImplementation(true);
Nicolas Geoffray47171752020-08-31 15:03:20 +0100533 DCHECK(!method->HasCodeItem()) << method->PrettyMethod();
534 DCHECK(method->GetSingleImplementation(pointer_size) == nullptr) << method->PrettyMethod();
Mingyao Yange8fcd012017-01-20 10:43:30 -0800535 }
Nicolas Geoffray7aca9d52018-09-07 11:13:33 +0100536 // Default conflicting methods cannot be treated with single implementations,
537 // as we need to call them (and not inline them) in case of ICCE.
538 // See class_linker.cc:EnsureThrowsInvocationError.
539 } else if (!method->IsDefaultConflicting()) {
Mingyao Yang063fc772016-08-02 11:02:54 -0700540 method->SetHasSingleImplementation(true);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800541 // Single implementation of non-abstract method is itself.
542 DCHECK_EQ(method->GetSingleImplementation(pointer_size), method);
Mingyao Yang063fc772016-08-02 11:02:54 -0700543 }
544}
545
546void ClassHierarchyAnalysis::UpdateAfterLoadingOf(Handle<mirror::Class> klass) {
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000547 PointerSize image_pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
Mingyao Yang063fc772016-08-02 11:02:54 -0700548 if (klass->IsInterface()) {
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000549 for (ArtMethod& method : klass->GetDeclaredVirtualMethods(image_pointer_size)) {
550 DCHECK(method.IsAbstract() || method.IsDefault());
551 InitSingleImplementationFlag(klass, &method, image_pointer_size);
552 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700553 return;
554 }
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000555
Andreas Gampe98104992018-10-16 12:49:47 -0700556 ObjPtr<mirror::Class> super_class = klass->GetSuperClass();
Mingyao Yang063fc772016-08-02 11:02:54 -0700557 if (super_class == nullptr) {
558 return;
559 }
560
561 // Keeps track of all methods whose single-implementation assumption
562 // is invalidated by linking `klass`.
563 std::unordered_set<ArtMethod*> invalidated_single_impl_methods;
564
Mingyao Yang063fc772016-08-02 11:02:54 -0700565 // Do an entry-by-entry comparison of vtable contents with super's vtable.
566 for (int32_t i = 0; i < super_class->GetVTableLength(); ++i) {
567 ArtMethod* method = klass->GetVTableEntry(i, image_pointer_size);
568 ArtMethod* method_in_super = super_class->GetVTableEntry(i, image_pointer_size);
569 if (method == method_in_super) {
570 // vtable slot entry is inherited from super class.
Mingyao Yange8fcd012017-01-20 10:43:30 -0800571 if (method->IsAbstract() && klass->IsInstantiable()) {
572 // An instantiable class that inherits an abstract method is treated as
573 // supplying an implementation that throws AbstractMethodError.
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000574 CheckVirtualMethodSingleImplementationInfo(klass,
575 method,
576 method_in_super,
577 invalidated_single_impl_methods,
578 image_pointer_size);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800579 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700580 continue;
581 }
Mingyao Yange8fcd012017-01-20 10:43:30 -0800582 InitSingleImplementationFlag(klass, method, image_pointer_size);
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000583 CheckVirtualMethodSingleImplementationInfo(klass,
584 method,
585 method_in_super,
586 invalidated_single_impl_methods,
587 image_pointer_size);
Mingyao Yang063fc772016-08-02 11:02:54 -0700588 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700589 // For new virtual methods that don't override.
590 for (int32_t i = super_class->GetVTableLength(); i < klass->GetVTableLength(); ++i) {
591 ArtMethod* method = klass->GetVTableEntry(i, image_pointer_size);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800592 InitSingleImplementationFlag(klass, method, image_pointer_size);
Mingyao Yang063fc772016-08-02 11:02:54 -0700593 }
594
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000595 if (klass->IsInstantiable()) {
Vladimir Markoc524e9e2019-03-26 10:54:50 +0000596 ObjPtr<mirror::IfTable> iftable = klass->GetIfTable();
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000597 const size_t ifcount = klass->GetIfTableCount();
598 for (size_t i = 0; i < ifcount; ++i) {
Vladimir Marko557fece2019-03-26 14:29:41 +0000599 ObjPtr<mirror::Class> interface = iftable->GetInterface(i);
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000600 for (size_t j = 0, count = iftable->GetMethodArrayCount(i); j < count; ++j) {
601 ArtMethod* interface_method = interface->GetVirtualMethod(j, image_pointer_size);
Vladimir Marko557fece2019-03-26 14:29:41 +0000602 ObjPtr<mirror::PointerArray> method_array = iftable->GetMethodArray(i);
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000603 ArtMethod* implementation_method =
604 method_array->GetElementPtrSize<ArtMethod*>(j, image_pointer_size);
605 DCHECK(implementation_method != nullptr) << klass->PrettyClass();
606 CheckInterfaceMethodSingleImplementationInfo(klass,
607 interface_method,
608 implementation_method,
609 invalidated_single_impl_methods,
610 image_pointer_size);
611 }
612 }
613 }
614
615 InvalidateSingleImplementationMethods(invalidated_single_impl_methods);
616}
617
618void ClassHierarchyAnalysis::InvalidateSingleImplementationMethods(
619 std::unordered_set<ArtMethod*>& invalidated_single_impl_methods) {
Mingyao Yang063fc772016-08-02 11:02:54 -0700620 if (!invalidated_single_impl_methods.empty()) {
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000621 Runtime* const runtime = Runtime::Current();
Mingyao Yang063fc772016-08-02 11:02:54 -0700622 Thread *self = Thread::Current();
623 // Method headers for compiled code to be invalidated.
624 std::unordered_set<OatQuickMethodHeader*> dependent_method_headers;
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000625 PointerSize image_pointer_size =
626 Runtime::Current()->GetClassLinker()->GetImagePointerSize();
Mingyao Yang063fc772016-08-02 11:02:54 -0700627
628 {
629 // We do this under cha_lock_. Committing code also grabs this lock to
630 // make sure the code is only committed when all single-implementation
631 // assumptions are still true.
Alex Light33b7b5d2018-08-07 19:13:51 +0000632 std::vector<std::pair<ArtMethod*, OatQuickMethodHeader*>> headers;
633 {
634 MutexLock cha_mu(self, *Locks::cha_lock_);
635 // Invalidate compiled methods that assume some virtual calls have only
636 // single implementations.
637 for (ArtMethod* invalidated : invalidated_single_impl_methods) {
638 if (!invalidated->HasSingleImplementation()) {
639 // It might have been invalidated already when other class linking is
640 // going on.
641 continue;
642 }
643 invalidated->SetHasSingleImplementation(false);
644 if (invalidated->IsAbstract()) {
645 // Clear the single implementation method.
646 invalidated->SetSingleImplementation(nullptr, image_pointer_size);
647 }
Alex Light8dde74e2018-08-07 19:11:05 +0000648
Alex Light33b7b5d2018-08-07 19:13:51 +0000649 if (runtime->IsAotCompiler()) {
650 // No need to invalidate any compiled code as the AotCompiler doesn't
651 // run any code.
652 continue;
653 }
Alex Light8dde74e2018-08-07 19:11:05 +0000654
Alex Light33b7b5d2018-08-07 19:13:51 +0000655 // Invalidate all dependents.
656 for (const auto& dependent : GetDependents(invalidated)) {
657 ArtMethod* method = dependent.first;;
658 OatQuickMethodHeader* method_header = dependent.second;
659 VLOG(class_linker) << "CHA invalidated compiled code for " << method->PrettyMethod();
660 DCHECK(runtime->UseJitCompilation());
661 // We need to call JitCodeCache::InvalidateCompiledCodeFor but we cannot do it here
662 // since it would run into problems with lock-ordering. We don't want to re-order the
663 // locks since that would make code-commit racy.
664 headers.push_back({method, method_header});
665 dependent_method_headers.insert(method_header);
666 }
667 RemoveAllDependenciesFor(invalidated);
Alex Light8dde74e2018-08-07 19:11:05 +0000668 }
Alex Light33b7b5d2018-08-07 19:13:51 +0000669 }
670 // Since we are still loading the class that invalidated the code it's fine we have this after
671 // getting rid of the dependency. Any calls would need to be with the old version (since the
672 // new one isn't loaded yet) which still works fine. We will deoptimize just after this to
673 // ensure everything gets the new state.
674 jit::Jit* jit = Runtime::Current()->GetJit();
675 if (jit != nullptr) {
676 jit::JitCodeCache* code_cache = jit->GetCodeCache();
677 for (const auto& pair : headers) {
678 code_cache->InvalidateCompiledCodeFor(pair.first, pair.second);
679 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700680 }
681 }
682
683 if (dependent_method_headers.empty()) {
684 return;
685 }
686 // Deoptimze compiled code on stack that should have been invalidated.
687 CHACheckpoint checkpoint(dependent_method_headers);
688 size_t threads_running_checkpoint = runtime->GetThreadList()->RunCheckpoint(&checkpoint);
689 if (threads_running_checkpoint != 0) {
690 checkpoint.WaitForThreadsToRunThroughCheckpoint(threads_running_checkpoint);
691 }
692 }
693}
694
Mathieu Chartiercf79cf52017-07-21 11:17:57 -0700695void ClassHierarchyAnalysis::RemoveDependenciesForLinearAlloc(const LinearAlloc* linear_alloc) {
696 MutexLock mu(Thread::Current(), *Locks::cha_lock_);
697 for (auto it = cha_dependency_map_.begin(); it != cha_dependency_map_.end(); ) {
698 // Use unsafe to avoid locking since the allocator is going to be deleted.
699 if (linear_alloc->ContainsUnsafe(it->first)) {
700 // About to delete the ArtMethod, erase the entry from the map.
701 it = cha_dependency_map_.erase(it);
702 } else {
703 ++it;
704 }
705 }
706}
707
Mingyao Yang063fc772016-08-02 11:02:54 -0700708} // namespace art