blob: 6c011e8e39d7f20f0f6d1bfc62c208166e466a0c [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"
Mathieu Chartiercf79cf52017-07-21 11:17:57 -070022#include "linear_alloc.h"
Mingyao Yang063fc772016-08-02 11:02:54 -070023#include "runtime.h"
24#include "scoped_thread_state_change-inl.h"
25#include "stack.h"
26#include "thread.h"
27#include "thread_list.h"
28#include "thread_pool.h"
29
30namespace art {
31
32void ClassHierarchyAnalysis::AddDependency(ArtMethod* method,
33 ArtMethod* dependent_method,
34 OatQuickMethodHeader* dependent_header) {
Mingyao Yangcc104502017-05-24 17:13:03 -070035 const auto it = cha_dependency_map_.insert(
36 decltype(cha_dependency_map_)::value_type(method, ListOfDependentPairs())).first;
37 it->second.push_back({dependent_method, dependent_header});
Mingyao Yang063fc772016-08-02 11:02:54 -070038}
39
Mingyao Yangcc104502017-05-24 17:13:03 -070040static const ClassHierarchyAnalysis::ListOfDependentPairs s_empty_vector;
41
42const ClassHierarchyAnalysis::ListOfDependentPairs& ClassHierarchyAnalysis::GetDependents(
43 ArtMethod* method) {
Mingyao Yang063fc772016-08-02 11:02:54 -070044 auto it = cha_dependency_map_.find(method);
45 if (it != cha_dependency_map_.end()) {
Mingyao Yang063fc772016-08-02 11:02:54 -070046 return it->second;
47 }
Mingyao Yangcc104502017-05-24 17:13:03 -070048 return s_empty_vector;
Mingyao Yang063fc772016-08-02 11:02:54 -070049}
50
Mingyao Yangcc104502017-05-24 17:13:03 -070051void ClassHierarchyAnalysis::RemoveAllDependenciesFor(ArtMethod* method) {
52 cha_dependency_map_.erase(method);
Mingyao Yang063fc772016-08-02 11:02:54 -070053}
54
55void ClassHierarchyAnalysis::RemoveDependentsWithMethodHeaders(
56 const std::unordered_set<OatQuickMethodHeader*>& method_headers) {
57 // Iterate through all entries in the dependency map and remove any entry that
58 // contains one of those in method_headers.
59 for (auto map_it = cha_dependency_map_.begin(); map_it != cha_dependency_map_.end(); ) {
Mingyao Yangcc104502017-05-24 17:13:03 -070060 ListOfDependentPairs& dependents = map_it->second;
61 dependents.erase(
62 std::remove_if(
63 dependents.begin(),
64 dependents.end(),
65 [&method_headers](MethodAndMethodHeaderPair& dependent) {
66 return method_headers.find(dependent.second) != method_headers.end();
67 }),
68 dependents.end());
69
Mingyao Yang063fc772016-08-02 11:02:54 -070070 // Remove the map entry if there are no more dependents.
Mingyao Yangcc104502017-05-24 17:13:03 -070071 if (dependents.empty()) {
Mingyao Yang063fc772016-08-02 11:02:54 -070072 map_it = cha_dependency_map_.erase(map_it);
Mingyao Yang063fc772016-08-02 11:02:54 -070073 } else {
74 map_it++;
75 }
76 }
77}
78
79// This stack visitor walks the stack and for compiled code with certain method
80// headers, sets the should_deoptimize flag on stack to 1.
81// TODO: also set the register value to 1 when should_deoptimize is allocated in
82// a register.
83class CHAStackVisitor FINAL : public StackVisitor {
84 public:
85 CHAStackVisitor(Thread* thread_in,
86 Context* context,
87 const std::unordered_set<OatQuickMethodHeader*>& method_headers)
88 : StackVisitor(thread_in, context, StackVisitor::StackWalkKind::kSkipInlinedFrames),
89 method_headers_(method_headers) {
90 }
91
92 bool VisitFrame() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
93 ArtMethod* method = GetMethod();
Mingyao Yang7b9a83f2016-12-13 12:28:31 -080094 // Avoid types of methods that do not have an oat quick method header.
95 if (method == nullptr ||
96 method->IsRuntimeMethod() ||
97 method->IsNative() ||
98 method->IsProxyMethod()) {
Mingyao Yang063fc772016-08-02 11:02:54 -070099 return true;
100 }
101 if (GetCurrentQuickFrame() == nullptr) {
102 // Not compiled code.
103 return true;
104 }
105 // Method may have multiple versions of compiled code. Check
106 // the method header to see if it has should_deoptimize flag.
107 const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
Mingyao Yang7b9a83f2016-12-13 12:28:31 -0800108 DCHECK(method_header != nullptr);
Mingyao Yang063fc772016-08-02 11:02:54 -0700109 if (!method_header->HasShouldDeoptimizeFlag()) {
110 // This compiled version doesn't have should_deoptimize flag. Skip.
111 return true;
112 }
113 auto it = std::find(method_headers_.begin(), method_headers_.end(), method_header);
114 if (it == method_headers_.end()) {
115 // Not in the list of method headers that should be deoptimized.
116 return true;
117 }
118
119 // The compiled code on stack is not valid anymore. Need to deoptimize.
120 SetShouldDeoptimizeFlag();
121
122 return true;
123 }
124
125 private:
126 void SetShouldDeoptimizeFlag() REQUIRES_SHARED(Locks::mutator_lock_) {
127 QuickMethodFrameInfo frame_info = GetCurrentQuickFrameInfo();
128 size_t frame_size = frame_info.FrameSizeInBytes();
129 uint8_t* sp = reinterpret_cast<uint8_t*>(GetCurrentQuickFrame());
130 size_t core_spill_size = POPCOUNT(frame_info.CoreSpillMask()) *
131 GetBytesPerGprSpillLocation(kRuntimeISA);
132 size_t fpu_spill_size = POPCOUNT(frame_info.FpSpillMask()) *
133 GetBytesPerFprSpillLocation(kRuntimeISA);
134 size_t offset = frame_size - core_spill_size - fpu_spill_size - kShouldDeoptimizeFlagSize;
135 uint8_t* should_deoptimize_addr = sp + offset;
136 // Set deoptimization flag to 1.
137 DCHECK(*should_deoptimize_addr == 0 || *should_deoptimize_addr == 1);
138 *should_deoptimize_addr = 1;
139 }
140
141 // Set of method headers for compiled code that should be deoptimized.
142 const std::unordered_set<OatQuickMethodHeader*>& method_headers_;
143
144 DISALLOW_COPY_AND_ASSIGN(CHAStackVisitor);
145};
146
147class CHACheckpoint FINAL : public Closure {
148 public:
149 explicit CHACheckpoint(const std::unordered_set<OatQuickMethodHeader*>& method_headers)
150 : barrier_(0),
151 method_headers_(method_headers) {}
152
153 void Run(Thread* thread) OVERRIDE {
154 // Note thread and self may not be equal if thread was already suspended at
155 // the point of the request.
156 Thread* self = Thread::Current();
157 ScopedObjectAccess soa(self);
158 CHAStackVisitor visitor(thread, nullptr, method_headers_);
159 visitor.WalkStack();
160 barrier_.Pass(self);
161 }
162
163 void WaitForThreadsToRunThroughCheckpoint(size_t threads_running_checkpoint) {
164 Thread* self = Thread::Current();
165 ScopedThreadStateChange tsc(self, kWaitingForCheckPointsToRun);
166 barrier_.Increment(self, threads_running_checkpoint);
167 }
168
169 private:
170 // The barrier to be passed through and for the requestor to wait upon.
171 Barrier barrier_;
172 // List of method headers for invalidated compiled code.
173 const std::unordered_set<OatQuickMethodHeader*>& method_headers_;
174
175 DISALLOW_COPY_AND_ASSIGN(CHACheckpoint);
176};
177
Andreas Gampe582d96a2017-07-24 13:51:47 -0700178
179static void VerifyNonSingleImplementation(mirror::Class* verify_class,
180 uint16_t verify_index,
181 ArtMethod* excluded_method)
182 REQUIRES_SHARED(Locks::mutator_lock_) {
183 if (!kIsDebugBuild) {
184 return;
185 }
186
Mingyao Yang063fc772016-08-02 11:02:54 -0700187 // Grab cha_lock_ to make sure all single-implementation updates are seen.
Andreas Gampe582d96a2017-07-24 13:51:47 -0700188 MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
189
Mingyao Yang063fc772016-08-02 11:02:54 -0700190 PointerSize image_pointer_size =
191 Runtime::Current()->GetClassLinker()->GetImagePointerSize();
Andreas Gampe582d96a2017-07-24 13:51:47 -0700192
193 mirror::Class* input_verify_class = verify_class;
194
Mingyao Yang063fc772016-08-02 11:02:54 -0700195 while (verify_class != nullptr) {
196 if (verify_index >= verify_class->GetVTableLength()) {
197 return;
198 }
199 ArtMethod* verify_method = verify_class->GetVTableEntry(verify_index, image_pointer_size);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800200 if (verify_method != excluded_method) {
Andreas Gampe582d96a2017-07-24 13:51:47 -0700201 auto construct_parent_chain = [](mirror::Class* failed, mirror::Class* in)
202 REQUIRES_SHARED(Locks::mutator_lock_) {
203 std::string tmp = in->PrettyClass();
204 while (in != failed) {
205 in = in->GetSuperClass();
206 tmp = tmp + "->" + in->PrettyClass();
207 }
208 return tmp;
209 };
Mingyao Yange8fcd012017-01-20 10:43:30 -0800210 DCHECK(!verify_method->HasSingleImplementation())
211 << "class: " << verify_class->PrettyClass()
Mingyao Yang37c8e5c2017-02-10 11:25:05 -0800212 << " verify_method: " << verify_method->PrettyMethod(true)
Andreas Gampe582d96a2017-07-24 13:51:47 -0700213 << " (" << construct_parent_chain(verify_class, input_verify_class) << ")"
214 << " excluded_method: " << ArtMethod::PrettyMethod(excluded_method);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800215 if (verify_method->IsAbstract()) {
216 DCHECK(verify_method->GetSingleImplementation(image_pointer_size) == nullptr);
217 }
218 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700219 verify_class = verify_class->GetSuperClass();
220 }
221}
222
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000223void ClassHierarchyAnalysis::CheckVirtualMethodSingleImplementationInfo(
Mingyao Yang063fc772016-08-02 11:02:54 -0700224 Handle<mirror::Class> klass,
225 ArtMethod* virtual_method,
226 ArtMethod* method_in_super,
Mingyao Yange8fcd012017-01-20 10:43:30 -0800227 std::unordered_set<ArtMethod*>& invalidated_single_impl_methods,
228 PointerSize pointer_size) {
Mingyao Yang063fc772016-08-02 11:02:54 -0700229 // TODO: if klass is not instantiable, virtual_method isn't invocable yet so
230 // even if it overrides, it doesn't invalidate single-implementation
231 // assumption.
232
Mingyao Yange8fcd012017-01-20 10:43:30 -0800233 DCHECK((virtual_method != method_in_super) || virtual_method->IsAbstract());
Mingyao Yang063fc772016-08-02 11:02:54 -0700234 DCHECK(method_in_super->GetDeclaringClass()->IsResolved()) << "class isn't resolved";
235 // If virtual_method doesn't come from a default interface method, it should
236 // be supplied by klass.
Mingyao Yange8fcd012017-01-20 10:43:30 -0800237 DCHECK(virtual_method == method_in_super ||
238 virtual_method->IsCopied() ||
Mingyao Yang063fc772016-08-02 11:02:54 -0700239 virtual_method->GetDeclaringClass() == klass.Get());
240
Mingyao Yange8fcd012017-01-20 10:43:30 -0800241 // To make updating single-implementation flags simple, we always maintain the following
242 // invariant:
243 // Say all virtual methods in the same vtable slot, starting from the bottom child class
244 // to super classes, is a sequence of unique methods m3, m2, m1, ... (after removing duplicate
245 // methods for inherited methods).
246 // For example for the following class hierarchy,
247 // class A { void m() { ... } }
248 // class B extends A { void m() { ... } }
249 // class C extends B {}
250 // class D extends C { void m() { ... } }
251 // the sequence is D.m(), B.m(), A.m().
252 // The single-implementation status for that sequence of methods begin with one or two true's,
253 // then become all falses. The only case where two true's are possible is for one abstract
254 // method m and one non-abstract method mImpl that overrides method m.
255 // With the invariant, when linking in a new class, we only need to at most update one or
256 // two methods in the sequence for their single-implementation status, in order to maintain
257 // the invariant.
258
Mingyao Yang063fc772016-08-02 11:02:54 -0700259 if (!method_in_super->HasSingleImplementation()) {
260 // method_in_super already has multiple implementations. All methods in the
261 // same vtable slots in its super classes should have
262 // non-single-implementation already.
Andreas Gampe582d96a2017-07-24 13:51:47 -0700263 VerifyNonSingleImplementation(klass->GetSuperClass()->GetSuperClass(),
264 method_in_super->GetMethodIndex(),
265 nullptr /* excluded_method */);
Mingyao Yang063fc772016-08-02 11:02:54 -0700266 return;
267 }
268
Mingyao Yange8fcd012017-01-20 10:43:30 -0800269 uint16_t method_index = method_in_super->GetMethodIndex();
270 if (method_in_super->IsAbstract()) {
Andreas Gampe582d96a2017-07-24 13:51:47 -0700271 // An abstract method should have made all methods in the same vtable
272 // slot above it in the class hierarchy having non-single-implementation.
273 VerifyNonSingleImplementation(klass->GetSuperClass()->GetSuperClass(),
274 method_index,
275 method_in_super);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800276
277 if (virtual_method->IsAbstract()) {
278 // SUPER: abstract, VIRTUAL: abstract.
279 if (method_in_super == virtual_method) {
280 DCHECK(klass->IsInstantiable());
281 // An instantiable subclass hasn't provided a concrete implementation of
282 // the abstract method. Invoking method_in_super may throw AbstractMethodError.
283 // This is an uncommon case, so we simply treat method_in_super as not
284 // having single-implementation.
285 invalidated_single_impl_methods.insert(method_in_super);
286 return;
287 } else {
288 // One abstract method overrides another abstract method. This is an uncommon
289 // case. We simply treat method_in_super as not having single-implementation.
290 invalidated_single_impl_methods.insert(method_in_super);
291 return;
292 }
293 } else {
294 // SUPER: abstract, VIRTUAL: non-abstract.
295 // A non-abstract method overrides an abstract method.
296 if (method_in_super->GetSingleImplementation(pointer_size) == nullptr) {
297 // Abstract method_in_super has no implementation yet.
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000298 // We need to grab cha_lock_ since there may be multiple class linking
299 // going on that can check/modify the single-implementation flag/method
300 // of method_in_super.
Mingyao Yange8fcd012017-01-20 10:43:30 -0800301 MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
302 if (!method_in_super->HasSingleImplementation()) {
303 return;
304 }
305 if (method_in_super->GetSingleImplementation(pointer_size) == nullptr) {
306 // virtual_method becomes the first implementation for method_in_super.
307 method_in_super->SetSingleImplementation(virtual_method, pointer_size);
308 // Keep method_in_super's single-implementation status.
309 return;
310 }
311 // Fall through to invalidate method_in_super's single-implementation status.
312 }
313 // Abstract method_in_super already got one implementation.
314 // Invalidate method_in_super's single-implementation status.
315 invalidated_single_impl_methods.insert(method_in_super);
316 return;
317 }
318 } else {
319 if (virtual_method->IsAbstract()) {
320 // SUPER: non-abstract, VIRTUAL: abstract.
321 // An abstract method overrides a non-abstract method. This is an uncommon
322 // case, we simply treat both methods as not having single-implementation.
323 invalidated_single_impl_methods.insert(virtual_method);
324 // Fall-through to handle invalidating method_in_super of its
325 // single-implementation status.
326 }
327
328 // SUPER: non-abstract, VIRTUAL: non-abstract/abstract(fall-through from previous if).
329 // Invalidate method_in_super's single-implementation status.
330 invalidated_single_impl_methods.insert(method_in_super);
331
332 // method_in_super might be the single-implementation of another abstract method,
333 // which should be also invalidated of its single-implementation status.
334 mirror::Class* super_super = klass->GetSuperClass()->GetSuperClass();
335 while (super_super != nullptr &&
336 method_index < super_super->GetVTableLength()) {
337 ArtMethod* method_in_super_super = super_super->GetVTableEntry(method_index, pointer_size);
338 if (method_in_super_super != method_in_super) {
339 if (method_in_super_super->IsAbstract()) {
340 if (method_in_super_super->HasSingleImplementation()) {
341 // Invalidate method_in_super's single-implementation status.
342 invalidated_single_impl_methods.insert(method_in_super_super);
343 // No need to further traverse up the class hierarchy since if there
344 // are cases that one abstract method overrides another method, we
345 // should have made that method having non-single-implementation already.
346 } else {
347 // method_in_super_super is already non-single-implementation.
348 // No need to further traverse up the class hierarchy.
349 }
350 } else {
351 DCHECK(!method_in_super_super->HasSingleImplementation());
352 // No need to further traverse up the class hierarchy since two non-abstract
353 // methods (method_in_super and method_in_super_super) should have set all
354 // other methods (abstract or not) in the vtable slot to be non-single-implementation.
355 }
356
Andreas Gampe582d96a2017-07-24 13:51:47 -0700357 VerifyNonSingleImplementation(super_super->GetSuperClass(),
358 method_index,
359 method_in_super_super);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800360 // No need to go any further.
361 return;
362 } else {
363 super_super = super_super->GetSuperClass();
364 }
365 }
366 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700367}
368
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000369void ClassHierarchyAnalysis::CheckInterfaceMethodSingleImplementationInfo(
370 Handle<mirror::Class> klass,
371 ArtMethod* interface_method,
372 ArtMethod* implementation_method,
373 std::unordered_set<ArtMethod*>& invalidated_single_impl_methods,
374 PointerSize pointer_size) {
375 DCHECK(klass->IsInstantiable());
376 DCHECK(interface_method->IsAbstract() || interface_method->IsDefault());
377
378 if (!interface_method->HasSingleImplementation()) {
379 return;
380 }
381
382 if (implementation_method->IsAbstract()) {
383 // An instantiable class doesn't supply an implementation for
384 // interface_method. Invoking the interface method on the class will throw
385 // AbstractMethodError. This is an uncommon case, so we simply treat
386 // interface_method as not having single-implementation.
387 invalidated_single_impl_methods.insert(interface_method);
388 return;
389 }
390
391 // We need to grab cha_lock_ since there may be multiple class linking going
392 // on that can check/modify the single-implementation flag/method of
393 // interface_method.
394 MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
395 // Do this check again after we grab cha_lock_.
396 if (!interface_method->HasSingleImplementation()) {
397 return;
398 }
399
400 ArtMethod* single_impl = interface_method->GetSingleImplementation(pointer_size);
401 if (single_impl == nullptr) {
402 // implementation_method becomes the first implementation for
403 // interface_method.
404 interface_method->SetSingleImplementation(implementation_method, pointer_size);
405 // Keep interface_method's single-implementation status.
406 return;
407 }
408 DCHECK(!single_impl->IsAbstract());
409 if (single_impl->GetDeclaringClass() == implementation_method->GetDeclaringClass()) {
410 // Same implementation. Since implementation_method may be a copy of a default
411 // method, we need to check the declaring class for equality.
412 return;
413 }
414 // Another implementation for interface_method.
415 invalidated_single_impl_methods.insert(interface_method);
416}
417
Mingyao Yang063fc772016-08-02 11:02:54 -0700418void ClassHierarchyAnalysis::InitSingleImplementationFlag(Handle<mirror::Class> klass,
Mingyao Yange8fcd012017-01-20 10:43:30 -0800419 ArtMethod* method,
420 PointerSize pointer_size) {
Mingyao Yang063fc772016-08-02 11:02:54 -0700421 DCHECK(method->IsCopied() || method->GetDeclaringClass() == klass.Get());
422 if (klass->IsFinal() || method->IsFinal()) {
423 // Final classes or methods do not need CHA for devirtualization.
424 // This frees up modifier bits for intrinsics which currently are only
425 // used for static methods or methods of final classes.
426 return;
427 }
Mingyao Yang37c8e5c2017-02-10 11:25:05 -0800428 if (method->IsAbstract()) {
429 // single-implementation of abstract method shares the same field
430 // that's used for JNI function of native method. It's fine since a method
431 // cannot be both abstract and native.
432 DCHECK(!method->IsNative()) << "Abstract method cannot be native";
433
Mingyao Yange8fcd012017-01-20 10:43:30 -0800434 if (method->GetDeclaringClass()->IsInstantiable()) {
435 // Rare case, but we do accept it (such as 800-smali/smali/b_26143249.smali).
436 // Do not attempt to devirtualize it.
437 method->SetHasSingleImplementation(false);
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000438 DCHECK(method->GetSingleImplementation(pointer_size) == nullptr);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800439 } else {
440 // Abstract method starts with single-implementation flag set and null
441 // implementation method.
442 method->SetHasSingleImplementation(true);
443 DCHECK(method->GetSingleImplementation(pointer_size) == nullptr);
444 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700445 } else {
446 method->SetHasSingleImplementation(true);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800447 // Single implementation of non-abstract method is itself.
448 DCHECK_EQ(method->GetSingleImplementation(pointer_size), method);
Mingyao Yang063fc772016-08-02 11:02:54 -0700449 }
450}
451
452void ClassHierarchyAnalysis::UpdateAfterLoadingOf(Handle<mirror::Class> klass) {
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000453 PointerSize image_pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
Mingyao Yang063fc772016-08-02 11:02:54 -0700454 if (klass->IsInterface()) {
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000455 for (ArtMethod& method : klass->GetDeclaredVirtualMethods(image_pointer_size)) {
456 DCHECK(method.IsAbstract() || method.IsDefault());
457 InitSingleImplementationFlag(klass, &method, image_pointer_size);
458 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700459 return;
460 }
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000461
Mingyao Yang063fc772016-08-02 11:02:54 -0700462 mirror::Class* super_class = klass->GetSuperClass();
463 if (super_class == nullptr) {
464 return;
465 }
466
467 // Keeps track of all methods whose single-implementation assumption
468 // is invalidated by linking `klass`.
469 std::unordered_set<ArtMethod*> invalidated_single_impl_methods;
470
Mingyao Yang063fc772016-08-02 11:02:54 -0700471 // Do an entry-by-entry comparison of vtable contents with super's vtable.
472 for (int32_t i = 0; i < super_class->GetVTableLength(); ++i) {
473 ArtMethod* method = klass->GetVTableEntry(i, image_pointer_size);
474 ArtMethod* method_in_super = super_class->GetVTableEntry(i, image_pointer_size);
475 if (method == method_in_super) {
476 // vtable slot entry is inherited from super class.
Mingyao Yange8fcd012017-01-20 10:43:30 -0800477 if (method->IsAbstract() && klass->IsInstantiable()) {
478 // An instantiable class that inherits an abstract method is treated as
479 // supplying an implementation that throws AbstractMethodError.
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000480 CheckVirtualMethodSingleImplementationInfo(klass,
481 method,
482 method_in_super,
483 invalidated_single_impl_methods,
484 image_pointer_size);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800485 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700486 continue;
487 }
Mingyao Yange8fcd012017-01-20 10:43:30 -0800488 InitSingleImplementationFlag(klass, method, image_pointer_size);
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000489 CheckVirtualMethodSingleImplementationInfo(klass,
490 method,
491 method_in_super,
492 invalidated_single_impl_methods,
493 image_pointer_size);
Mingyao Yang063fc772016-08-02 11:02:54 -0700494 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700495 // For new virtual methods that don't override.
496 for (int32_t i = super_class->GetVTableLength(); i < klass->GetVTableLength(); ++i) {
497 ArtMethod* method = klass->GetVTableEntry(i, image_pointer_size);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800498 InitSingleImplementationFlag(klass, method, image_pointer_size);
Mingyao Yang063fc772016-08-02 11:02:54 -0700499 }
500
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000501 if (klass->IsInstantiable()) {
502 auto* iftable = klass->GetIfTable();
503 const size_t ifcount = klass->GetIfTableCount();
504 for (size_t i = 0; i < ifcount; ++i) {
505 mirror::Class* interface = iftable->GetInterface(i);
506 for (size_t j = 0, count = iftable->GetMethodArrayCount(i); j < count; ++j) {
507 ArtMethod* interface_method = interface->GetVirtualMethod(j, image_pointer_size);
508 mirror::PointerArray* method_array = iftable->GetMethodArray(i);
509 ArtMethod* implementation_method =
510 method_array->GetElementPtrSize<ArtMethod*>(j, image_pointer_size);
511 DCHECK(implementation_method != nullptr) << klass->PrettyClass();
512 CheckInterfaceMethodSingleImplementationInfo(klass,
513 interface_method,
514 implementation_method,
515 invalidated_single_impl_methods,
516 image_pointer_size);
517 }
518 }
519 }
520
521 InvalidateSingleImplementationMethods(invalidated_single_impl_methods);
522}
523
524void ClassHierarchyAnalysis::InvalidateSingleImplementationMethods(
525 std::unordered_set<ArtMethod*>& invalidated_single_impl_methods) {
Mingyao Yang063fc772016-08-02 11:02:54 -0700526 if (!invalidated_single_impl_methods.empty()) {
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000527 Runtime* const runtime = Runtime::Current();
Mingyao Yang063fc772016-08-02 11:02:54 -0700528 Thread *self = Thread::Current();
529 // Method headers for compiled code to be invalidated.
530 std::unordered_set<OatQuickMethodHeader*> dependent_method_headers;
Nicolas Geoffray18ea1c92017-03-27 08:00:18 +0000531 PointerSize image_pointer_size =
532 Runtime::Current()->GetClassLinker()->GetImagePointerSize();
Mingyao Yang063fc772016-08-02 11:02:54 -0700533
534 {
535 // We do this under cha_lock_. Committing code also grabs this lock to
536 // make sure the code is only committed when all single-implementation
537 // assumptions are still true.
538 MutexLock cha_mu(self, *Locks::cha_lock_);
539 // Invalidate compiled methods that assume some virtual calls have only
540 // single implementations.
541 for (ArtMethod* invalidated : invalidated_single_impl_methods) {
542 if (!invalidated->HasSingleImplementation()) {
543 // It might have been invalidated already when other class linking is
544 // going on.
545 continue;
546 }
547 invalidated->SetHasSingleImplementation(false);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800548 if (invalidated->IsAbstract()) {
549 // Clear the single implementation method.
550 invalidated->SetSingleImplementation(nullptr, image_pointer_size);
551 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700552
553 if (runtime->IsAotCompiler()) {
554 // No need to invalidate any compiled code as the AotCompiler doesn't
555 // run any code.
556 continue;
557 }
558
559 // Invalidate all dependents.
Mingyao Yangcc104502017-05-24 17:13:03 -0700560 for (const auto& dependent : GetDependents(invalidated)) {
Mingyao Yang063fc772016-08-02 11:02:54 -0700561 ArtMethod* method = dependent.first;;
562 OatQuickMethodHeader* method_header = dependent.second;
563 VLOG(class_linker) << "CHA invalidated compiled code for " << method->PrettyMethod();
564 DCHECK(runtime->UseJitCompilation());
565 runtime->GetJit()->GetCodeCache()->InvalidateCompiledCodeFor(
566 method, method_header);
567 dependent_method_headers.insert(method_header);
568 }
Mingyao Yangcc104502017-05-24 17:13:03 -0700569 RemoveAllDependenciesFor(invalidated);
Mingyao Yang063fc772016-08-02 11:02:54 -0700570 }
571 }
572
573 if (dependent_method_headers.empty()) {
574 return;
575 }
576 // Deoptimze compiled code on stack that should have been invalidated.
577 CHACheckpoint checkpoint(dependent_method_headers);
578 size_t threads_running_checkpoint = runtime->GetThreadList()->RunCheckpoint(&checkpoint);
579 if (threads_running_checkpoint != 0) {
580 checkpoint.WaitForThreadsToRunThroughCheckpoint(threads_running_checkpoint);
581 }
582 }
583}
584
Mathieu Chartiercf79cf52017-07-21 11:17:57 -0700585void ClassHierarchyAnalysis::RemoveDependenciesForLinearAlloc(const LinearAlloc* linear_alloc) {
586 MutexLock mu(Thread::Current(), *Locks::cha_lock_);
587 for (auto it = cha_dependency_map_.begin(); it != cha_dependency_map_.end(); ) {
588 // Use unsafe to avoid locking since the allocator is going to be deleted.
589 if (linear_alloc->ContainsUnsafe(it->first)) {
590 // About to delete the ArtMethod, erase the entry from the map.
591 it = cha_dependency_map_.erase(it);
592 } else {
593 ++it;
594 }
595 }
596}
597
Mingyao Yang063fc772016-08-02 11:02:54 -0700598} // namespace art