blob: 8eeebf30edda88e51f1c17de9a80ed34a91d44ab [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"
Mingyao Yang063fc772016-08-02 11:02:54 -070020#include "jit/jit.h"
21#include "jit/jit_code_cache.h"
22#include "runtime.h"
23#include "scoped_thread_state_change-inl.h"
24#include "stack.h"
25#include "thread.h"
26#include "thread_list.h"
27#include "thread_pool.h"
28
29namespace art {
30
31void ClassHierarchyAnalysis::AddDependency(ArtMethod* method,
32 ArtMethod* dependent_method,
33 OatQuickMethodHeader* dependent_header) {
Mingyao Yangcc104502017-05-24 17:13:03 -070034 const auto it = cha_dependency_map_.insert(
35 decltype(cha_dependency_map_)::value_type(method, ListOfDependentPairs())).first;
36 it->second.push_back({dependent_method, dependent_header});
Mingyao Yang063fc772016-08-02 11:02:54 -070037}
38
Mingyao Yangcc104502017-05-24 17:13:03 -070039static const ClassHierarchyAnalysis::ListOfDependentPairs s_empty_vector;
40
41const ClassHierarchyAnalysis::ListOfDependentPairs& ClassHierarchyAnalysis::GetDependents(
42 ArtMethod* method) {
Mingyao Yang063fc772016-08-02 11:02:54 -070043 auto it = cha_dependency_map_.find(method);
44 if (it != cha_dependency_map_.end()) {
Mingyao Yang063fc772016-08-02 11:02:54 -070045 return it->second;
46 }
Mingyao Yangcc104502017-05-24 17:13:03 -070047 return s_empty_vector;
Mingyao Yang063fc772016-08-02 11:02:54 -070048}
49
Mingyao Yangcc104502017-05-24 17:13:03 -070050void ClassHierarchyAnalysis::RemoveAllDependenciesFor(ArtMethod* method) {
51 cha_dependency_map_.erase(method);
Mingyao Yang063fc772016-08-02 11:02:54 -070052}
53
54void ClassHierarchyAnalysis::RemoveDependentsWithMethodHeaders(
55 const std::unordered_set<OatQuickMethodHeader*>& method_headers) {
56 // Iterate through all entries in the dependency map and remove any entry that
57 // contains one of those in method_headers.
58 for (auto map_it = cha_dependency_map_.begin(); map_it != cha_dependency_map_.end(); ) {
Mingyao Yangcc104502017-05-24 17:13:03 -070059 ListOfDependentPairs& dependents = map_it->second;
60 dependents.erase(
61 std::remove_if(
62 dependents.begin(),
63 dependents.end(),
64 [&method_headers](MethodAndMethodHeaderPair& dependent) {
65 return method_headers.find(dependent.second) != method_headers.end();
66 }),
67 dependents.end());
68
Mingyao Yang063fc772016-08-02 11:02:54 -070069 // Remove the map entry if there are no more dependents.
Mingyao Yangcc104502017-05-24 17:13:03 -070070 if (dependents.empty()) {
Mingyao Yang063fc772016-08-02 11:02:54 -070071 map_it = cha_dependency_map_.erase(map_it);
Mingyao Yang063fc772016-08-02 11:02:54 -070072 } else {
73 map_it++;
74 }
75 }
76}
77
78// This stack visitor walks the stack and for compiled code with certain method
79// headers, sets the should_deoptimize flag on stack to 1.
80// TODO: also set the register value to 1 when should_deoptimize is allocated in
81// a register.
82class CHAStackVisitor FINAL : public StackVisitor {
83 public:
84 CHAStackVisitor(Thread* thread_in,
85 Context* context,
86 const std::unordered_set<OatQuickMethodHeader*>& method_headers)
87 : StackVisitor(thread_in, context, StackVisitor::StackWalkKind::kSkipInlinedFrames),
88 method_headers_(method_headers) {
89 }
90
91 bool VisitFrame() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
92 ArtMethod* method = GetMethod();
Mingyao Yang7b9a83f2016-12-13 12:28:31 -080093 // Avoid types of methods that do not have an oat quick method header.
94 if (method == nullptr ||
95 method->IsRuntimeMethod() ||
96 method->IsNative() ||
97 method->IsProxyMethod()) {
Mingyao Yang063fc772016-08-02 11:02:54 -070098 return true;
99 }
100 if (GetCurrentQuickFrame() == nullptr) {
101 // Not compiled code.
102 return true;
103 }
104 // Method may have multiple versions of compiled code. Check
105 // the method header to see if it has should_deoptimize flag.
106 const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
Mingyao Yang7b9a83f2016-12-13 12:28:31 -0800107 DCHECK(method_header != nullptr);
Mingyao Yang063fc772016-08-02 11:02:54 -0700108 if (!method_header->HasShouldDeoptimizeFlag()) {
109 // This compiled version doesn't have should_deoptimize flag. Skip.
110 return true;
111 }
112 auto it = std::find(method_headers_.begin(), method_headers_.end(), method_header);
113 if (it == method_headers_.end()) {
114 // Not in the list of method headers that should be deoptimized.
115 return true;
116 }
117
118 // The compiled code on stack is not valid anymore. Need to deoptimize.
119 SetShouldDeoptimizeFlag();
120
121 return true;
122 }
123
124 private:
125 void SetShouldDeoptimizeFlag() REQUIRES_SHARED(Locks::mutator_lock_) {
126 QuickMethodFrameInfo frame_info = GetCurrentQuickFrameInfo();
127 size_t frame_size = frame_info.FrameSizeInBytes();
128 uint8_t* sp = reinterpret_cast<uint8_t*>(GetCurrentQuickFrame());
129 size_t core_spill_size = POPCOUNT(frame_info.CoreSpillMask()) *
130 GetBytesPerGprSpillLocation(kRuntimeISA);
131 size_t fpu_spill_size = POPCOUNT(frame_info.FpSpillMask()) *
132 GetBytesPerFprSpillLocation(kRuntimeISA);
133 size_t offset = frame_size - core_spill_size - fpu_spill_size - kShouldDeoptimizeFlagSize;
134 uint8_t* should_deoptimize_addr = sp + offset;
135 // Set deoptimization flag to 1.
136 DCHECK(*should_deoptimize_addr == 0 || *should_deoptimize_addr == 1);
137 *should_deoptimize_addr = 1;
138 }
139
140 // Set of method headers for compiled code that should be deoptimized.
141 const std::unordered_set<OatQuickMethodHeader*>& method_headers_;
142
143 DISALLOW_COPY_AND_ASSIGN(CHAStackVisitor);
144};
145
146class CHACheckpoint FINAL : public Closure {
147 public:
148 explicit CHACheckpoint(const std::unordered_set<OatQuickMethodHeader*>& method_headers)
149 : barrier_(0),
150 method_headers_(method_headers) {}
151
152 void Run(Thread* thread) OVERRIDE {
153 // Note thread and self may not be equal if thread was already suspended at
154 // the point of the request.
155 Thread* self = Thread::Current();
156 ScopedObjectAccess soa(self);
157 CHAStackVisitor visitor(thread, nullptr, method_headers_);
158 visitor.WalkStack();
159 barrier_.Pass(self);
160 }
161
162 void WaitForThreadsToRunThroughCheckpoint(size_t threads_running_checkpoint) {
163 Thread* self = Thread::Current();
164 ScopedThreadStateChange tsc(self, kWaitingForCheckPointsToRun);
165 barrier_.Increment(self, threads_running_checkpoint);
166 }
167
168 private:
169 // The barrier to be passed through and for the requestor to wait upon.
170 Barrier barrier_;
171 // List of method headers for invalidated compiled code.
172 const std::unordered_set<OatQuickMethodHeader*>& method_headers_;
173
174 DISALLOW_COPY_AND_ASSIGN(CHACheckpoint);
175};
176
Andreas Gampe582d96a2017-07-24 13:51:47 -0700177
178static void VerifyNonSingleImplementation(mirror::Class* verify_class,
179 uint16_t verify_index,
180 ArtMethod* excluded_method)
181 REQUIRES_SHARED(Locks::mutator_lock_) {
182 if (!kIsDebugBuild) {
183 return;
184 }
185
Mingyao Yang063fc772016-08-02 11:02:54 -0700186 // Grab cha_lock_ to make sure all single-implementation updates are seen.
Andreas Gampe582d96a2017-07-24 13:51:47 -0700187 MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
188
Mingyao Yang063fc772016-08-02 11:02:54 -0700189 PointerSize image_pointer_size =
190 Runtime::Current()->GetClassLinker()->GetImagePointerSize();
Andreas Gampe582d96a2017-07-24 13:51:47 -0700191
192 mirror::Class* input_verify_class = verify_class;
193
Mingyao Yang063fc772016-08-02 11:02:54 -0700194 while (verify_class != nullptr) {
195 if (verify_index >= verify_class->GetVTableLength()) {
196 return;
197 }
198 ArtMethod* verify_method = verify_class->GetVTableEntry(verify_index, image_pointer_size);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800199 if (verify_method != excluded_method) {
Andreas Gampe582d96a2017-07-24 13:51:47 -0700200 auto construct_parent_chain = [](mirror::Class* failed, mirror::Class* in)
201 REQUIRES_SHARED(Locks::mutator_lock_) {
202 std::string tmp = in->PrettyClass();
203 while (in != failed) {
204 in = in->GetSuperClass();
205 tmp = tmp + "->" + in->PrettyClass();
206 }
207 return tmp;
208 };
Mingyao Yange8fcd012017-01-20 10:43:30 -0800209 DCHECK(!verify_method->HasSingleImplementation())
210 << "class: " << verify_class->PrettyClass()
Mingyao Yang37c8e5c2017-02-10 11:25:05 -0800211 << " verify_method: " << verify_method->PrettyMethod(true)
Andreas Gampe582d96a2017-07-24 13:51:47 -0700212 << " (" << construct_parent_chain(verify_class, input_verify_class) << ")"
213 << " excluded_method: " << ArtMethod::PrettyMethod(excluded_method);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800214 if (verify_method->IsAbstract()) {
215 DCHECK(verify_method->GetSingleImplementation(image_pointer_size) == nullptr);
216 }
217 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700218 verify_class = verify_class->GetSuperClass();
219 }
220}
221
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000222void ClassHierarchyAnalysis::CheckVirtualMethodSingleImplementationInfo(
Mingyao Yang063fc772016-08-02 11:02:54 -0700223 Handle<mirror::Class> klass,
224 ArtMethod* virtual_method,
225 ArtMethod* method_in_super,
Mingyao Yange8fcd012017-01-20 10:43:30 -0800226 std::unordered_set<ArtMethod*>& invalidated_single_impl_methods,
227 PointerSize pointer_size) {
Mingyao Yang063fc772016-08-02 11:02:54 -0700228 // TODO: if klass is not instantiable, virtual_method isn't invocable yet so
229 // even if it overrides, it doesn't invalidate single-implementation
230 // assumption.
231
Mingyao Yange8fcd012017-01-20 10:43:30 -0800232 DCHECK((virtual_method != method_in_super) || virtual_method->IsAbstract());
Mingyao Yang063fc772016-08-02 11:02:54 -0700233 DCHECK(method_in_super->GetDeclaringClass()->IsResolved()) << "class isn't resolved";
234 // If virtual_method doesn't come from a default interface method, it should
235 // be supplied by klass.
Mingyao Yange8fcd012017-01-20 10:43:30 -0800236 DCHECK(virtual_method == method_in_super ||
237 virtual_method->IsCopied() ||
Mingyao Yang063fc772016-08-02 11:02:54 -0700238 virtual_method->GetDeclaringClass() == klass.Get());
239
Mingyao Yange8fcd012017-01-20 10:43:30 -0800240 // To make updating single-implementation flags simple, we always maintain the following
241 // invariant:
242 // Say all virtual methods in the same vtable slot, starting from the bottom child class
243 // to super classes, is a sequence of unique methods m3, m2, m1, ... (after removing duplicate
244 // methods for inherited methods).
245 // For example for the following class hierarchy,
246 // class A { void m() { ... } }
247 // class B extends A { void m() { ... } }
248 // class C extends B {}
249 // class D extends C { void m() { ... } }
250 // the sequence is D.m(), B.m(), A.m().
251 // The single-implementation status for that sequence of methods begin with one or two true's,
252 // then become all falses. The only case where two true's are possible is for one abstract
253 // method m and one non-abstract method mImpl that overrides method m.
254 // With the invariant, when linking in a new class, we only need to at most update one or
255 // two methods in the sequence for their single-implementation status, in order to maintain
256 // the invariant.
257
Mingyao Yang063fc772016-08-02 11:02:54 -0700258 if (!method_in_super->HasSingleImplementation()) {
259 // method_in_super already has multiple implementations. All methods in the
260 // same vtable slots in its super classes should have
261 // non-single-implementation already.
Andreas Gampe582d96a2017-07-24 13:51:47 -0700262 VerifyNonSingleImplementation(klass->GetSuperClass()->GetSuperClass(),
263 method_in_super->GetMethodIndex(),
264 nullptr /* excluded_method */);
Mingyao Yang063fc772016-08-02 11:02:54 -0700265 return;
266 }
267
Mingyao Yange8fcd012017-01-20 10:43:30 -0800268 uint16_t method_index = method_in_super->GetMethodIndex();
269 if (method_in_super->IsAbstract()) {
Andreas Gampe582d96a2017-07-24 13:51:47 -0700270 // An abstract method should have made all methods in the same vtable
271 // slot above it in the class hierarchy having non-single-implementation.
272 VerifyNonSingleImplementation(klass->GetSuperClass()->GetSuperClass(),
273 method_index,
274 method_in_super);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800275
276 if (virtual_method->IsAbstract()) {
277 // SUPER: abstract, VIRTUAL: abstract.
278 if (method_in_super == virtual_method) {
279 DCHECK(klass->IsInstantiable());
280 // An instantiable subclass hasn't provided a concrete implementation of
281 // the abstract method. Invoking method_in_super may throw AbstractMethodError.
282 // This is an uncommon case, so we simply treat method_in_super as not
283 // having single-implementation.
284 invalidated_single_impl_methods.insert(method_in_super);
285 return;
286 } else {
287 // One abstract method overrides another abstract method. This is an uncommon
288 // case. We simply treat method_in_super as not having single-implementation.
289 invalidated_single_impl_methods.insert(method_in_super);
290 return;
291 }
292 } else {
293 // SUPER: abstract, VIRTUAL: non-abstract.
294 // A non-abstract method overrides an abstract method.
295 if (method_in_super->GetSingleImplementation(pointer_size) == nullptr) {
296 // Abstract method_in_super has no implementation yet.
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000297 // We need to grab cha_lock_ since there may be multiple class linking
298 // going on that can check/modify the single-implementation flag/method
299 // of method_in_super.
Mingyao Yange8fcd012017-01-20 10:43:30 -0800300 MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
301 if (!method_in_super->HasSingleImplementation()) {
302 return;
303 }
304 if (method_in_super->GetSingleImplementation(pointer_size) == nullptr) {
305 // virtual_method becomes the first implementation for method_in_super.
306 method_in_super->SetSingleImplementation(virtual_method, pointer_size);
307 // Keep method_in_super's single-implementation status.
308 return;
309 }
310 // Fall through to invalidate method_in_super's single-implementation status.
311 }
312 // Abstract method_in_super already got one implementation.
313 // Invalidate method_in_super's single-implementation status.
314 invalidated_single_impl_methods.insert(method_in_super);
315 return;
316 }
317 } else {
318 if (virtual_method->IsAbstract()) {
319 // SUPER: non-abstract, VIRTUAL: abstract.
320 // An abstract method overrides a non-abstract method. This is an uncommon
321 // case, we simply treat both methods as not having single-implementation.
322 invalidated_single_impl_methods.insert(virtual_method);
323 // Fall-through to handle invalidating method_in_super of its
324 // single-implementation status.
325 }
326
327 // SUPER: non-abstract, VIRTUAL: non-abstract/abstract(fall-through from previous if).
328 // Invalidate method_in_super's single-implementation status.
329 invalidated_single_impl_methods.insert(method_in_super);
330
331 // method_in_super might be the single-implementation of another abstract method,
332 // which should be also invalidated of its single-implementation status.
333 mirror::Class* super_super = klass->GetSuperClass()->GetSuperClass();
334 while (super_super != nullptr &&
335 method_index < super_super->GetVTableLength()) {
336 ArtMethod* method_in_super_super = super_super->GetVTableEntry(method_index, pointer_size);
337 if (method_in_super_super != method_in_super) {
338 if (method_in_super_super->IsAbstract()) {
339 if (method_in_super_super->HasSingleImplementation()) {
340 // Invalidate method_in_super's single-implementation status.
341 invalidated_single_impl_methods.insert(method_in_super_super);
342 // No need to further traverse up the class hierarchy since if there
343 // are cases that one abstract method overrides another method, we
344 // should have made that method having non-single-implementation already.
345 } else {
346 // method_in_super_super is already non-single-implementation.
347 // No need to further traverse up the class hierarchy.
348 }
349 } else {
350 DCHECK(!method_in_super_super->HasSingleImplementation());
351 // No need to further traverse up the class hierarchy since two non-abstract
352 // methods (method_in_super and method_in_super_super) should have set all
353 // other methods (abstract or not) in the vtable slot to be non-single-implementation.
354 }
355
Andreas Gampe582d96a2017-07-24 13:51:47 -0700356 VerifyNonSingleImplementation(super_super->GetSuperClass(),
357 method_index,
358 method_in_super_super);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800359 // No need to go any further.
360 return;
361 } else {
362 super_super = super_super->GetSuperClass();
363 }
364 }
365 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700366}
367
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000368void ClassHierarchyAnalysis::CheckInterfaceMethodSingleImplementationInfo(
369 Handle<mirror::Class> klass,
370 ArtMethod* interface_method,
371 ArtMethod* implementation_method,
372 std::unordered_set<ArtMethod*>& invalidated_single_impl_methods,
373 PointerSize pointer_size) {
374 DCHECK(klass->IsInstantiable());
375 DCHECK(interface_method->IsAbstract() || interface_method->IsDefault());
376
377 if (!interface_method->HasSingleImplementation()) {
378 return;
379 }
380
381 if (implementation_method->IsAbstract()) {
382 // An instantiable class doesn't supply an implementation for
383 // interface_method. Invoking the interface method on the class will throw
384 // AbstractMethodError. This is an uncommon case, so we simply treat
385 // interface_method as not having single-implementation.
386 invalidated_single_impl_methods.insert(interface_method);
387 return;
388 }
389
390 // We need to grab cha_lock_ since there may be multiple class linking going
391 // on that can check/modify the single-implementation flag/method of
392 // interface_method.
393 MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
394 // Do this check again after we grab cha_lock_.
395 if (!interface_method->HasSingleImplementation()) {
396 return;
397 }
398
399 ArtMethod* single_impl = interface_method->GetSingleImplementation(pointer_size);
400 if (single_impl == nullptr) {
401 // implementation_method becomes the first implementation for
402 // interface_method.
403 interface_method->SetSingleImplementation(implementation_method, pointer_size);
404 // Keep interface_method's single-implementation status.
405 return;
406 }
407 DCHECK(!single_impl->IsAbstract());
408 if (single_impl->GetDeclaringClass() == implementation_method->GetDeclaringClass()) {
409 // Same implementation. Since implementation_method may be a copy of a default
410 // method, we need to check the declaring class for equality.
411 return;
412 }
413 // Another implementation for interface_method.
414 invalidated_single_impl_methods.insert(interface_method);
415}
416
Mingyao Yang063fc772016-08-02 11:02:54 -0700417void ClassHierarchyAnalysis::InitSingleImplementationFlag(Handle<mirror::Class> klass,
Mingyao Yange8fcd012017-01-20 10:43:30 -0800418 ArtMethod* method,
419 PointerSize pointer_size) {
Mingyao Yang063fc772016-08-02 11:02:54 -0700420 DCHECK(method->IsCopied() || method->GetDeclaringClass() == klass.Get());
421 if (klass->IsFinal() || method->IsFinal()) {
422 // Final classes or methods do not need CHA for devirtualization.
423 // This frees up modifier bits for intrinsics which currently are only
424 // used for static methods or methods of final classes.
425 return;
426 }
Mingyao Yang37c8e5c2017-02-10 11:25:05 -0800427 if (method->IsAbstract()) {
428 // single-implementation of abstract method shares the same field
429 // that's used for JNI function of native method. It's fine since a method
430 // cannot be both abstract and native.
431 DCHECK(!method->IsNative()) << "Abstract method cannot be native";
432
Mingyao Yange8fcd012017-01-20 10:43:30 -0800433 if (method->GetDeclaringClass()->IsInstantiable()) {
434 // Rare case, but we do accept it (such as 800-smali/smali/b_26143249.smali).
435 // Do not attempt to devirtualize it.
436 method->SetHasSingleImplementation(false);
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000437 DCHECK(method->GetSingleImplementation(pointer_size) == nullptr);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800438 } else {
439 // Abstract method starts with single-implementation flag set and null
440 // implementation method.
441 method->SetHasSingleImplementation(true);
442 DCHECK(method->GetSingleImplementation(pointer_size) == nullptr);
443 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700444 } else {
445 method->SetHasSingleImplementation(true);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800446 // Single implementation of non-abstract method is itself.
447 DCHECK_EQ(method->GetSingleImplementation(pointer_size), method);
Mingyao Yang063fc772016-08-02 11:02:54 -0700448 }
449}
450
451void ClassHierarchyAnalysis::UpdateAfterLoadingOf(Handle<mirror::Class> klass) {
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000452 PointerSize image_pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
Mingyao Yang063fc772016-08-02 11:02:54 -0700453 if (klass->IsInterface()) {
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000454 for (ArtMethod& method : klass->GetDeclaredVirtualMethods(image_pointer_size)) {
455 DCHECK(method.IsAbstract() || method.IsDefault());
456 InitSingleImplementationFlag(klass, &method, image_pointer_size);
457 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700458 return;
459 }
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000460
Mingyao Yang063fc772016-08-02 11:02:54 -0700461 mirror::Class* super_class = klass->GetSuperClass();
462 if (super_class == nullptr) {
463 return;
464 }
465
466 // Keeps track of all methods whose single-implementation assumption
467 // is invalidated by linking `klass`.
468 std::unordered_set<ArtMethod*> invalidated_single_impl_methods;
469
Mingyao Yang063fc772016-08-02 11:02:54 -0700470 // Do an entry-by-entry comparison of vtable contents with super's vtable.
471 for (int32_t i = 0; i < super_class->GetVTableLength(); ++i) {
472 ArtMethod* method = klass->GetVTableEntry(i, image_pointer_size);
473 ArtMethod* method_in_super = super_class->GetVTableEntry(i, image_pointer_size);
474 if (method == method_in_super) {
475 // vtable slot entry is inherited from super class.
Mingyao Yange8fcd012017-01-20 10:43:30 -0800476 if (method->IsAbstract() && klass->IsInstantiable()) {
477 // An instantiable class that inherits an abstract method is treated as
478 // supplying an implementation that throws AbstractMethodError.
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000479 CheckVirtualMethodSingleImplementationInfo(klass,
480 method,
481 method_in_super,
482 invalidated_single_impl_methods,
483 image_pointer_size);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800484 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700485 continue;
486 }
Mingyao Yange8fcd012017-01-20 10:43:30 -0800487 InitSingleImplementationFlag(klass, method, image_pointer_size);
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000488 CheckVirtualMethodSingleImplementationInfo(klass,
489 method,
490 method_in_super,
491 invalidated_single_impl_methods,
492 image_pointer_size);
Mingyao Yang063fc772016-08-02 11:02:54 -0700493 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700494 // For new virtual methods that don't override.
495 for (int32_t i = super_class->GetVTableLength(); i < klass->GetVTableLength(); ++i) {
496 ArtMethod* method = klass->GetVTableEntry(i, image_pointer_size);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800497 InitSingleImplementationFlag(klass, method, image_pointer_size);
Mingyao Yang063fc772016-08-02 11:02:54 -0700498 }
499
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000500 if (klass->IsInstantiable()) {
501 auto* iftable = klass->GetIfTable();
502 const size_t ifcount = klass->GetIfTableCount();
503 for (size_t i = 0; i < ifcount; ++i) {
504 mirror::Class* interface = iftable->GetInterface(i);
505 for (size_t j = 0, count = iftable->GetMethodArrayCount(i); j < count; ++j) {
506 ArtMethod* interface_method = interface->GetVirtualMethod(j, image_pointer_size);
507 mirror::PointerArray* method_array = iftable->GetMethodArray(i);
508 ArtMethod* implementation_method =
509 method_array->GetElementPtrSize<ArtMethod*>(j, image_pointer_size);
510 DCHECK(implementation_method != nullptr) << klass->PrettyClass();
511 CheckInterfaceMethodSingleImplementationInfo(klass,
512 interface_method,
513 implementation_method,
514 invalidated_single_impl_methods,
515 image_pointer_size);
516 }
517 }
518 }
519
520 InvalidateSingleImplementationMethods(invalidated_single_impl_methods);
521}
522
523void ClassHierarchyAnalysis::InvalidateSingleImplementationMethods(
524 std::unordered_set<ArtMethod*>& invalidated_single_impl_methods) {
Mingyao Yang063fc772016-08-02 11:02:54 -0700525 if (!invalidated_single_impl_methods.empty()) {
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000526 Runtime* const runtime = Runtime::Current();
Mingyao Yang063fc772016-08-02 11:02:54 -0700527 Thread *self = Thread::Current();
528 // Method headers for compiled code to be invalidated.
529 std::unordered_set<OatQuickMethodHeader*> dependent_method_headers;
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000530 PointerSize image_pointer_size =
531 Runtime::Current()->GetClassLinker()->GetImagePointerSize();
Mingyao Yang063fc772016-08-02 11:02:54 -0700532
533 {
534 // We do this under cha_lock_. Committing code also grabs this lock to
535 // make sure the code is only committed when all single-implementation
536 // assumptions are still true.
537 MutexLock cha_mu(self, *Locks::cha_lock_);
538 // Invalidate compiled methods that assume some virtual calls have only
539 // single implementations.
540 for (ArtMethod* invalidated : invalidated_single_impl_methods) {
541 if (!invalidated->HasSingleImplementation()) {
542 // It might have been invalidated already when other class linking is
543 // going on.
544 continue;
545 }
546 invalidated->SetHasSingleImplementation(false);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800547 if (invalidated->IsAbstract()) {
548 // Clear the single implementation method.
549 invalidated->SetSingleImplementation(nullptr, image_pointer_size);
550 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700551
552 if (runtime->IsAotCompiler()) {
553 // No need to invalidate any compiled code as the AotCompiler doesn't
554 // run any code.
555 continue;
556 }
557
558 // Invalidate all dependents.
Mingyao Yangcc104502017-05-24 17:13:03 -0700559 for (const auto& dependent : GetDependents(invalidated)) {
Mingyao Yang063fc772016-08-02 11:02:54 -0700560 ArtMethod* method = dependent.first;;
561 OatQuickMethodHeader* method_header = dependent.second;
562 VLOG(class_linker) << "CHA invalidated compiled code for " << method->PrettyMethod();
563 DCHECK(runtime->UseJitCompilation());
564 runtime->GetJit()->GetCodeCache()->InvalidateCompiledCodeFor(
565 method, method_header);
566 dependent_method_headers.insert(method_header);
567 }
Mingyao Yangcc104502017-05-24 17:13:03 -0700568 RemoveAllDependenciesFor(invalidated);
Mingyao Yang063fc772016-08-02 11:02:54 -0700569 }
570 }
571
572 if (dependent_method_headers.empty()) {
573 return;
574 }
575 // Deoptimze compiled code on stack that should have been invalidated.
576 CHACheckpoint checkpoint(dependent_method_headers);
577 size_t threads_running_checkpoint = runtime->GetThreadList()->RunCheckpoint(&checkpoint);
578 if (threads_running_checkpoint != 0) {
579 checkpoint.WaitForThreadsToRunThroughCheckpoint(threads_running_checkpoint);
580 }
581 }
582}
583
584} // namespace art