blob: a53d7e5b250fd877d34fc0198f9ec2a9f6b07479 [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
Mingyao Yang063fc772016-08-02 11:02:54 -070021#include "jit/jit.h"
22#include "jit/jit_code_cache.h"
Mathieu Chartiercf79cf52017-07-21 11:17:57 -070023#include "linear_alloc.h"
Mingyao Yang063fc772016-08-02 11:02:54 -070024#include "runtime.h"
25#include "scoped_thread_state_change-inl.h"
26#include "stack.h"
27#include "thread.h"
28#include "thread_list.h"
29#include "thread_pool.h"
30
31namespace art {
32
33void ClassHierarchyAnalysis::AddDependency(ArtMethod* method,
34 ArtMethod* dependent_method,
35 OatQuickMethodHeader* dependent_header) {
Mingyao Yangcc104502017-05-24 17:13:03 -070036 const auto it = cha_dependency_map_.insert(
37 decltype(cha_dependency_map_)::value_type(method, ListOfDependentPairs())).first;
38 it->second.push_back({dependent_method, dependent_header});
Mingyao Yang063fc772016-08-02 11:02:54 -070039}
40
Mingyao Yangcc104502017-05-24 17:13:03 -070041static const ClassHierarchyAnalysis::ListOfDependentPairs s_empty_vector;
42
43const ClassHierarchyAnalysis::ListOfDependentPairs& ClassHierarchyAnalysis::GetDependents(
44 ArtMethod* method) {
Mingyao Yang063fc772016-08-02 11:02:54 -070045 auto it = cha_dependency_map_.find(method);
46 if (it != cha_dependency_map_.end()) {
Mingyao Yang063fc772016-08-02 11:02:54 -070047 return it->second;
48 }
Mingyao Yangcc104502017-05-24 17:13:03 -070049 return s_empty_vector;
Mingyao Yang063fc772016-08-02 11:02:54 -070050}
51
Mingyao Yangcc104502017-05-24 17:13:03 -070052void ClassHierarchyAnalysis::RemoveAllDependenciesFor(ArtMethod* method) {
53 cha_dependency_map_.erase(method);
Mingyao Yang063fc772016-08-02 11:02:54 -070054}
55
56void ClassHierarchyAnalysis::RemoveDependentsWithMethodHeaders(
57 const std::unordered_set<OatQuickMethodHeader*>& method_headers) {
58 // Iterate through all entries in the dependency map and remove any entry that
59 // contains one of those in method_headers.
60 for (auto map_it = cha_dependency_map_.begin(); map_it != cha_dependency_map_.end(); ) {
Mingyao Yangcc104502017-05-24 17:13:03 -070061 ListOfDependentPairs& dependents = map_it->second;
62 dependents.erase(
63 std::remove_if(
64 dependents.begin(),
65 dependents.end(),
66 [&method_headers](MethodAndMethodHeaderPair& dependent) {
67 return method_headers.find(dependent.second) != method_headers.end();
68 }),
69 dependents.end());
70
Mingyao Yang063fc772016-08-02 11:02:54 -070071 // Remove the map entry if there are no more dependents.
Mingyao Yangcc104502017-05-24 17:13:03 -070072 if (dependents.empty()) {
Mingyao Yang063fc772016-08-02 11:02:54 -070073 map_it = cha_dependency_map_.erase(map_it);
Mingyao Yang063fc772016-08-02 11:02:54 -070074 } else {
75 map_it++;
76 }
77 }
78}
79
80// This stack visitor walks the stack and for compiled code with certain method
81// headers, sets the should_deoptimize flag on stack to 1.
82// TODO: also set the register value to 1 when should_deoptimize is allocated in
83// a register.
84class CHAStackVisitor FINAL : public StackVisitor {
85 public:
86 CHAStackVisitor(Thread* thread_in,
87 Context* context,
88 const std::unordered_set<OatQuickMethodHeader*>& method_headers)
89 : StackVisitor(thread_in, context, StackVisitor::StackWalkKind::kSkipInlinedFrames),
90 method_headers_(method_headers) {
91 }
92
93 bool VisitFrame() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
94 ArtMethod* method = GetMethod();
Mingyao Yang7b9a83f2016-12-13 12:28:31 -080095 // Avoid types of methods that do not have an oat quick method header.
96 if (method == nullptr ||
97 method->IsRuntimeMethod() ||
98 method->IsNative() ||
99 method->IsProxyMethod()) {
Mingyao Yang063fc772016-08-02 11:02:54 -0700100 return true;
101 }
102 if (GetCurrentQuickFrame() == nullptr) {
103 // Not compiled code.
104 return true;
105 }
106 // Method may have multiple versions of compiled code. Check
107 // the method header to see if it has should_deoptimize flag.
108 const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
Mingyao Yang7b9a83f2016-12-13 12:28:31 -0800109 DCHECK(method_header != nullptr);
Mingyao Yang063fc772016-08-02 11:02:54 -0700110 if (!method_header->HasShouldDeoptimizeFlag()) {
111 // This compiled version doesn't have should_deoptimize flag. Skip.
112 return true;
113 }
114 auto it = std::find(method_headers_.begin(), method_headers_.end(), method_header);
115 if (it == method_headers_.end()) {
116 // Not in the list of method headers that should be deoptimized.
117 return true;
118 }
119
120 // The compiled code on stack is not valid anymore. Need to deoptimize.
121 SetShouldDeoptimizeFlag();
122
123 return true;
124 }
125
126 private:
127 void SetShouldDeoptimizeFlag() REQUIRES_SHARED(Locks::mutator_lock_) {
128 QuickMethodFrameInfo frame_info = GetCurrentQuickFrameInfo();
129 size_t frame_size = frame_info.FrameSizeInBytes();
130 uint8_t* sp = reinterpret_cast<uint8_t*>(GetCurrentQuickFrame());
131 size_t core_spill_size = POPCOUNT(frame_info.CoreSpillMask()) *
132 GetBytesPerGprSpillLocation(kRuntimeISA);
133 size_t fpu_spill_size = POPCOUNT(frame_info.FpSpillMask()) *
134 GetBytesPerFprSpillLocation(kRuntimeISA);
135 size_t offset = frame_size - core_spill_size - fpu_spill_size - kShouldDeoptimizeFlagSize;
136 uint8_t* should_deoptimize_addr = sp + offset;
137 // Set deoptimization flag to 1.
138 DCHECK(*should_deoptimize_addr == 0 || *should_deoptimize_addr == 1);
139 *should_deoptimize_addr = 1;
140 }
141
142 // Set of method headers for compiled code that should be deoptimized.
143 const std::unordered_set<OatQuickMethodHeader*>& method_headers_;
144
145 DISALLOW_COPY_AND_ASSIGN(CHAStackVisitor);
146};
147
148class CHACheckpoint FINAL : public Closure {
149 public:
150 explicit CHACheckpoint(const std::unordered_set<OatQuickMethodHeader*>& method_headers)
151 : barrier_(0),
152 method_headers_(method_headers) {}
153
154 void Run(Thread* thread) OVERRIDE {
155 // Note thread and self may not be equal if thread was already suspended at
156 // the point of the request.
157 Thread* self = Thread::Current();
158 ScopedObjectAccess soa(self);
159 CHAStackVisitor visitor(thread, nullptr, method_headers_);
160 visitor.WalkStack();
161 barrier_.Pass(self);
162 }
163
164 void WaitForThreadsToRunThroughCheckpoint(size_t threads_running_checkpoint) {
165 Thread* self = Thread::Current();
166 ScopedThreadStateChange tsc(self, kWaitingForCheckPointsToRun);
167 barrier_.Increment(self, threads_running_checkpoint);
168 }
169
170 private:
171 // The barrier to be passed through and for the requestor to wait upon.
172 Barrier barrier_;
173 // List of method headers for invalidated compiled code.
174 const std::unordered_set<OatQuickMethodHeader*>& method_headers_;
175
176 DISALLOW_COPY_AND_ASSIGN(CHACheckpoint);
177};
178
Andreas Gampe582d96a2017-07-24 13:51:47 -0700179
180static void VerifyNonSingleImplementation(mirror::Class* verify_class,
181 uint16_t verify_index,
182 ArtMethod* excluded_method)
183 REQUIRES_SHARED(Locks::mutator_lock_) {
184 if (!kIsDebugBuild) {
185 return;
186 }
187
Mingyao Yang063fc772016-08-02 11:02:54 -0700188 // Grab cha_lock_ to make sure all single-implementation updates are seen.
Andreas Gampe582d96a2017-07-24 13:51:47 -0700189 MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
190
Mingyao Yang063fc772016-08-02 11:02:54 -0700191 PointerSize image_pointer_size =
192 Runtime::Current()->GetClassLinker()->GetImagePointerSize();
Andreas Gampe582d96a2017-07-24 13:51:47 -0700193
194 mirror::Class* input_verify_class = verify_class;
195
Mingyao Yang063fc772016-08-02 11:02:54 -0700196 while (verify_class != nullptr) {
197 if (verify_index >= verify_class->GetVTableLength()) {
198 return;
199 }
200 ArtMethod* verify_method = verify_class->GetVTableEntry(verify_index, image_pointer_size);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800201 if (verify_method != excluded_method) {
Andreas Gampe582d96a2017-07-24 13:51:47 -0700202 auto construct_parent_chain = [](mirror::Class* failed, mirror::Class* in)
203 REQUIRES_SHARED(Locks::mutator_lock_) {
204 std::string tmp = in->PrettyClass();
205 while (in != failed) {
206 in = in->GetSuperClass();
207 tmp = tmp + "->" + in->PrettyClass();
208 }
209 return tmp;
210 };
Mingyao Yange8fcd012017-01-20 10:43:30 -0800211 DCHECK(!verify_method->HasSingleImplementation())
212 << "class: " << verify_class->PrettyClass()
Mingyao Yang37c8e5c2017-02-10 11:25:05 -0800213 << " verify_method: " << verify_method->PrettyMethod(true)
Andreas Gampe582d96a2017-07-24 13:51:47 -0700214 << " (" << construct_parent_chain(verify_class, input_verify_class) << ")"
215 << " excluded_method: " << ArtMethod::PrettyMethod(excluded_method);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800216 if (verify_method->IsAbstract()) {
217 DCHECK(verify_method->GetSingleImplementation(image_pointer_size) == nullptr);
218 }
219 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700220 verify_class = verify_class->GetSuperClass();
221 }
222}
223
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000224void ClassHierarchyAnalysis::CheckVirtualMethodSingleImplementationInfo(
Mingyao Yang063fc772016-08-02 11:02:54 -0700225 Handle<mirror::Class> klass,
226 ArtMethod* virtual_method,
227 ArtMethod* method_in_super,
Mingyao Yange8fcd012017-01-20 10:43:30 -0800228 std::unordered_set<ArtMethod*>& invalidated_single_impl_methods,
229 PointerSize pointer_size) {
Mingyao Yang063fc772016-08-02 11:02:54 -0700230 // TODO: if klass is not instantiable, virtual_method isn't invocable yet so
231 // even if it overrides, it doesn't invalidate single-implementation
232 // assumption.
233
Mingyao Yange8fcd012017-01-20 10:43:30 -0800234 DCHECK((virtual_method != method_in_super) || virtual_method->IsAbstract());
Mingyao Yang063fc772016-08-02 11:02:54 -0700235 DCHECK(method_in_super->GetDeclaringClass()->IsResolved()) << "class isn't resolved";
236 // If virtual_method doesn't come from a default interface method, it should
237 // be supplied by klass.
Mingyao Yange8fcd012017-01-20 10:43:30 -0800238 DCHECK(virtual_method == method_in_super ||
239 virtual_method->IsCopied() ||
Mingyao Yang063fc772016-08-02 11:02:54 -0700240 virtual_method->GetDeclaringClass() == klass.Get());
241
Mingyao Yange8fcd012017-01-20 10:43:30 -0800242 // To make updating single-implementation flags simple, we always maintain the following
243 // invariant:
244 // Say all virtual methods in the same vtable slot, starting from the bottom child class
245 // to super classes, is a sequence of unique methods m3, m2, m1, ... (after removing duplicate
246 // methods for inherited methods).
247 // For example for the following class hierarchy,
248 // class A { void m() { ... } }
249 // class B extends A { void m() { ... } }
250 // class C extends B {}
251 // class D extends C { void m() { ... } }
252 // the sequence is D.m(), B.m(), A.m().
253 // The single-implementation status for that sequence of methods begin with one or two true's,
254 // then become all falses. The only case where two true's are possible is for one abstract
255 // method m and one non-abstract method mImpl that overrides method m.
256 // With the invariant, when linking in a new class, we only need to at most update one or
257 // two methods in the sequence for their single-implementation status, in order to maintain
258 // the invariant.
259
Mingyao Yang063fc772016-08-02 11:02:54 -0700260 if (!method_in_super->HasSingleImplementation()) {
261 // method_in_super already has multiple implementations. All methods in the
262 // same vtable slots in its super classes should have
263 // non-single-implementation already.
Andreas Gampe582d96a2017-07-24 13:51:47 -0700264 VerifyNonSingleImplementation(klass->GetSuperClass()->GetSuperClass(),
265 method_in_super->GetMethodIndex(),
266 nullptr /* excluded_method */);
Mingyao Yang063fc772016-08-02 11:02:54 -0700267 return;
268 }
269
Mingyao Yange8fcd012017-01-20 10:43:30 -0800270 uint16_t method_index = method_in_super->GetMethodIndex();
271 if (method_in_super->IsAbstract()) {
Andreas Gampe582d96a2017-07-24 13:51:47 -0700272 // An abstract method should have made all methods in the same vtable
273 // slot above it in the class hierarchy having non-single-implementation.
274 VerifyNonSingleImplementation(klass->GetSuperClass()->GetSuperClass(),
275 method_index,
276 method_in_super);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800277
278 if (virtual_method->IsAbstract()) {
279 // SUPER: abstract, VIRTUAL: abstract.
280 if (method_in_super == virtual_method) {
281 DCHECK(klass->IsInstantiable());
282 // An instantiable subclass hasn't provided a concrete implementation of
283 // the abstract method. Invoking method_in_super may throw AbstractMethodError.
284 // This is an uncommon case, so we simply treat method_in_super as not
285 // having single-implementation.
286 invalidated_single_impl_methods.insert(method_in_super);
287 return;
288 } else {
289 // One abstract method overrides another abstract method. This is an uncommon
290 // case. We simply treat method_in_super as not having single-implementation.
291 invalidated_single_impl_methods.insert(method_in_super);
292 return;
293 }
294 } else {
295 // SUPER: abstract, VIRTUAL: non-abstract.
296 // A non-abstract method overrides an abstract method.
297 if (method_in_super->GetSingleImplementation(pointer_size) == nullptr) {
298 // Abstract method_in_super has no implementation yet.
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000299 // We need to grab cha_lock_ since there may be multiple class linking
300 // going on that can check/modify the single-implementation flag/method
301 // of method_in_super.
Mingyao Yange8fcd012017-01-20 10:43:30 -0800302 MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
303 if (!method_in_super->HasSingleImplementation()) {
304 return;
305 }
306 if (method_in_super->GetSingleImplementation(pointer_size) == nullptr) {
307 // virtual_method becomes the first implementation for method_in_super.
308 method_in_super->SetSingleImplementation(virtual_method, pointer_size);
309 // Keep method_in_super's single-implementation status.
310 return;
311 }
312 // Fall through to invalidate method_in_super's single-implementation status.
313 }
314 // Abstract method_in_super already got one implementation.
315 // Invalidate method_in_super's single-implementation status.
316 invalidated_single_impl_methods.insert(method_in_super);
317 return;
318 }
319 } else {
320 if (virtual_method->IsAbstract()) {
321 // SUPER: non-abstract, VIRTUAL: abstract.
322 // An abstract method overrides a non-abstract method. This is an uncommon
323 // case, we simply treat both methods as not having single-implementation.
324 invalidated_single_impl_methods.insert(virtual_method);
325 // Fall-through to handle invalidating method_in_super of its
326 // single-implementation status.
327 }
328
329 // SUPER: non-abstract, VIRTUAL: non-abstract/abstract(fall-through from previous if).
330 // Invalidate method_in_super's single-implementation status.
331 invalidated_single_impl_methods.insert(method_in_super);
332
333 // method_in_super might be the single-implementation of another abstract method,
334 // which should be also invalidated of its single-implementation status.
335 mirror::Class* super_super = klass->GetSuperClass()->GetSuperClass();
336 while (super_super != nullptr &&
337 method_index < super_super->GetVTableLength()) {
338 ArtMethod* method_in_super_super = super_super->GetVTableEntry(method_index, pointer_size);
339 if (method_in_super_super != method_in_super) {
340 if (method_in_super_super->IsAbstract()) {
341 if (method_in_super_super->HasSingleImplementation()) {
342 // Invalidate method_in_super's single-implementation status.
343 invalidated_single_impl_methods.insert(method_in_super_super);
344 // No need to further traverse up the class hierarchy since if there
345 // are cases that one abstract method overrides another method, we
346 // should have made that method having non-single-implementation already.
347 } else {
348 // method_in_super_super is already non-single-implementation.
349 // No need to further traverse up the class hierarchy.
350 }
351 } else {
352 DCHECK(!method_in_super_super->HasSingleImplementation());
353 // No need to further traverse up the class hierarchy since two non-abstract
354 // methods (method_in_super and method_in_super_super) should have set all
355 // other methods (abstract or not) in the vtable slot to be non-single-implementation.
356 }
357
Andreas Gampe582d96a2017-07-24 13:51:47 -0700358 VerifyNonSingleImplementation(super_super->GetSuperClass(),
359 method_index,
360 method_in_super_super);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800361 // No need to go any further.
362 return;
363 } else {
364 super_super = super_super->GetSuperClass();
365 }
366 }
367 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700368}
369
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000370void ClassHierarchyAnalysis::CheckInterfaceMethodSingleImplementationInfo(
371 Handle<mirror::Class> klass,
372 ArtMethod* interface_method,
373 ArtMethod* implementation_method,
374 std::unordered_set<ArtMethod*>& invalidated_single_impl_methods,
375 PointerSize pointer_size) {
376 DCHECK(klass->IsInstantiable());
377 DCHECK(interface_method->IsAbstract() || interface_method->IsDefault());
378
379 if (!interface_method->HasSingleImplementation()) {
380 return;
381 }
382
383 if (implementation_method->IsAbstract()) {
384 // An instantiable class doesn't supply an implementation for
385 // interface_method. Invoking the interface method on the class will throw
386 // AbstractMethodError. This is an uncommon case, so we simply treat
387 // interface_method as not having single-implementation.
388 invalidated_single_impl_methods.insert(interface_method);
389 return;
390 }
391
392 // We need to grab cha_lock_ since there may be multiple class linking going
393 // on that can check/modify the single-implementation flag/method of
394 // interface_method.
395 MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
396 // Do this check again after we grab cha_lock_.
397 if (!interface_method->HasSingleImplementation()) {
398 return;
399 }
400
401 ArtMethod* single_impl = interface_method->GetSingleImplementation(pointer_size);
402 if (single_impl == nullptr) {
403 // implementation_method becomes the first implementation for
404 // interface_method.
405 interface_method->SetSingleImplementation(implementation_method, pointer_size);
406 // Keep interface_method's single-implementation status.
407 return;
408 }
409 DCHECK(!single_impl->IsAbstract());
410 if (single_impl->GetDeclaringClass() == implementation_method->GetDeclaringClass()) {
411 // Same implementation. Since implementation_method may be a copy of a default
412 // method, we need to check the declaring class for equality.
413 return;
414 }
415 // Another implementation for interface_method.
416 invalidated_single_impl_methods.insert(interface_method);
417}
418
Mingyao Yang063fc772016-08-02 11:02:54 -0700419void ClassHierarchyAnalysis::InitSingleImplementationFlag(Handle<mirror::Class> klass,
Mingyao Yange8fcd012017-01-20 10:43:30 -0800420 ArtMethod* method,
421 PointerSize pointer_size) {
Mingyao Yang063fc772016-08-02 11:02:54 -0700422 DCHECK(method->IsCopied() || method->GetDeclaringClass() == klass.Get());
423 if (klass->IsFinal() || method->IsFinal()) {
424 // Final classes or methods do not need CHA for devirtualization.
425 // This frees up modifier bits for intrinsics which currently are only
426 // used for static methods or methods of final classes.
427 return;
428 }
Mingyao Yang37c8e5c2017-02-10 11:25:05 -0800429 if (method->IsAbstract()) {
430 // single-implementation of abstract method shares the same field
431 // that's used for JNI function of native method. It's fine since a method
432 // cannot be both abstract and native.
433 DCHECK(!method->IsNative()) << "Abstract method cannot be native";
434
Mingyao Yange8fcd012017-01-20 10:43:30 -0800435 if (method->GetDeclaringClass()->IsInstantiable()) {
436 // Rare case, but we do accept it (such as 800-smali/smali/b_26143249.smali).
437 // Do not attempt to devirtualize it.
438 method->SetHasSingleImplementation(false);
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000439 DCHECK(method->GetSingleImplementation(pointer_size) == nullptr);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800440 } else {
441 // Abstract method starts with single-implementation flag set and null
442 // implementation method.
443 method->SetHasSingleImplementation(true);
444 DCHECK(method->GetSingleImplementation(pointer_size) == nullptr);
445 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700446 } else {
447 method->SetHasSingleImplementation(true);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800448 // Single implementation of non-abstract method is itself.
449 DCHECK_EQ(method->GetSingleImplementation(pointer_size), method);
Mingyao Yang063fc772016-08-02 11:02:54 -0700450 }
451}
452
453void ClassHierarchyAnalysis::UpdateAfterLoadingOf(Handle<mirror::Class> klass) {
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000454 PointerSize image_pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
Mingyao Yang063fc772016-08-02 11:02:54 -0700455 if (klass->IsInterface()) {
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000456 for (ArtMethod& method : klass->GetDeclaredVirtualMethods(image_pointer_size)) {
457 DCHECK(method.IsAbstract() || method.IsDefault());
458 InitSingleImplementationFlag(klass, &method, image_pointer_size);
459 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700460 return;
461 }
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000462
Mingyao Yang063fc772016-08-02 11:02:54 -0700463 mirror::Class* super_class = klass->GetSuperClass();
464 if (super_class == nullptr) {
465 return;
466 }
467
468 // Keeps track of all methods whose single-implementation assumption
469 // is invalidated by linking `klass`.
470 std::unordered_set<ArtMethod*> invalidated_single_impl_methods;
471
Mingyao Yang063fc772016-08-02 11:02:54 -0700472 // Do an entry-by-entry comparison of vtable contents with super's vtable.
473 for (int32_t i = 0; i < super_class->GetVTableLength(); ++i) {
474 ArtMethod* method = klass->GetVTableEntry(i, image_pointer_size);
475 ArtMethod* method_in_super = super_class->GetVTableEntry(i, image_pointer_size);
476 if (method == method_in_super) {
477 // vtable slot entry is inherited from super class.
Mingyao Yange8fcd012017-01-20 10:43:30 -0800478 if (method->IsAbstract() && klass->IsInstantiable()) {
479 // An instantiable class that inherits an abstract method is treated as
480 // supplying an implementation that throws AbstractMethodError.
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000481 CheckVirtualMethodSingleImplementationInfo(klass,
482 method,
483 method_in_super,
484 invalidated_single_impl_methods,
485 image_pointer_size);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800486 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700487 continue;
488 }
Mingyao Yange8fcd012017-01-20 10:43:30 -0800489 InitSingleImplementationFlag(klass, method, image_pointer_size);
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000490 CheckVirtualMethodSingleImplementationInfo(klass,
491 method,
492 method_in_super,
493 invalidated_single_impl_methods,
494 image_pointer_size);
Mingyao Yang063fc772016-08-02 11:02:54 -0700495 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700496 // For new virtual methods that don't override.
497 for (int32_t i = super_class->GetVTableLength(); i < klass->GetVTableLength(); ++i) {
498 ArtMethod* method = klass->GetVTableEntry(i, image_pointer_size);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800499 InitSingleImplementationFlag(klass, method, image_pointer_size);
Mingyao Yang063fc772016-08-02 11:02:54 -0700500 }
501
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000502 if (klass->IsInstantiable()) {
503 auto* iftable = klass->GetIfTable();
504 const size_t ifcount = klass->GetIfTableCount();
505 for (size_t i = 0; i < ifcount; ++i) {
506 mirror::Class* interface = iftable->GetInterface(i);
507 for (size_t j = 0, count = iftable->GetMethodArrayCount(i); j < count; ++j) {
508 ArtMethod* interface_method = interface->GetVirtualMethod(j, image_pointer_size);
509 mirror::PointerArray* method_array = iftable->GetMethodArray(i);
510 ArtMethod* implementation_method =
511 method_array->GetElementPtrSize<ArtMethod*>(j, image_pointer_size);
512 DCHECK(implementation_method != nullptr) << klass->PrettyClass();
513 CheckInterfaceMethodSingleImplementationInfo(klass,
514 interface_method,
515 implementation_method,
516 invalidated_single_impl_methods,
517 image_pointer_size);
518 }
519 }
520 }
521
522 InvalidateSingleImplementationMethods(invalidated_single_impl_methods);
523}
524
525void ClassHierarchyAnalysis::InvalidateSingleImplementationMethods(
526 std::unordered_set<ArtMethod*>& invalidated_single_impl_methods) {
Mingyao Yang063fc772016-08-02 11:02:54 -0700527 if (!invalidated_single_impl_methods.empty()) {
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000528 Runtime* const runtime = Runtime::Current();
Mingyao Yang063fc772016-08-02 11:02:54 -0700529 Thread *self = Thread::Current();
530 // Method headers for compiled code to be invalidated.
531 std::unordered_set<OatQuickMethodHeader*> dependent_method_headers;
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000532 PointerSize image_pointer_size =
533 Runtime::Current()->GetClassLinker()->GetImagePointerSize();
Mingyao Yang063fc772016-08-02 11:02:54 -0700534
535 {
536 // We do this under cha_lock_. Committing code also grabs this lock to
537 // make sure the code is only committed when all single-implementation
538 // assumptions are still true.
539 MutexLock cha_mu(self, *Locks::cha_lock_);
540 // Invalidate compiled methods that assume some virtual calls have only
541 // single implementations.
542 for (ArtMethod* invalidated : invalidated_single_impl_methods) {
543 if (!invalidated->HasSingleImplementation()) {
544 // It might have been invalidated already when other class linking is
545 // going on.
546 continue;
547 }
548 invalidated->SetHasSingleImplementation(false);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800549 if (invalidated->IsAbstract()) {
550 // Clear the single implementation method.
551 invalidated->SetSingleImplementation(nullptr, image_pointer_size);
552 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700553
554 if (runtime->IsAotCompiler()) {
555 // No need to invalidate any compiled code as the AotCompiler doesn't
556 // run any code.
557 continue;
558 }
559
560 // Invalidate all dependents.
Mingyao Yangcc104502017-05-24 17:13:03 -0700561 for (const auto& dependent : GetDependents(invalidated)) {
Mingyao Yang063fc772016-08-02 11:02:54 -0700562 ArtMethod* method = dependent.first;;
563 OatQuickMethodHeader* method_header = dependent.second;
564 VLOG(class_linker) << "CHA invalidated compiled code for " << method->PrettyMethod();
565 DCHECK(runtime->UseJitCompilation());
566 runtime->GetJit()->GetCodeCache()->InvalidateCompiledCodeFor(
567 method, method_header);
568 dependent_method_headers.insert(method_header);
569 }
Mingyao Yangcc104502017-05-24 17:13:03 -0700570 RemoveAllDependenciesFor(invalidated);
Mingyao Yang063fc772016-08-02 11:02:54 -0700571 }
572 }
573
574 if (dependent_method_headers.empty()) {
575 return;
576 }
577 // Deoptimze compiled code on stack that should have been invalidated.
578 CHACheckpoint checkpoint(dependent_method_headers);
579 size_t threads_running_checkpoint = runtime->GetThreadList()->RunCheckpoint(&checkpoint);
580 if (threads_running_checkpoint != 0) {
581 checkpoint.WaitForThreadsToRunThroughCheckpoint(threads_running_checkpoint);
582 }
583 }
584}
585
Mathieu Chartiercf79cf52017-07-21 11:17:57 -0700586void ClassHierarchyAnalysis::RemoveDependenciesForLinearAlloc(const LinearAlloc* linear_alloc) {
587 MutexLock mu(Thread::Current(), *Locks::cha_lock_);
588 for (auto it = cha_dependency_map_.begin(); it != cha_dependency_map_.end(); ) {
589 // Use unsafe to avoid locking since the allocator is going to be deleted.
590 if (linear_alloc->ContainsUnsafe(it->first)) {
591 // About to delete the ArtMethod, erase the entry from the map.
592 it = cha_dependency_map_.erase(it);
593 } else {
594 ++it;
595 }
596 }
597}
598
Mingyao Yang063fc772016-08-02 11:02:54 -0700599} // namespace art