blob: e726bdbcb8bdd4ea7b6e793f070377be43dbe3ac [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
19#include "jit/jit.h"
20#include "jit/jit_code_cache.h"
21#include "runtime.h"
22#include "scoped_thread_state_change-inl.h"
23#include "stack.h"
24#include "thread.h"
25#include "thread_list.h"
26#include "thread_pool.h"
27
28namespace art {
29
30void ClassHierarchyAnalysis::AddDependency(ArtMethod* method,
31 ArtMethod* dependent_method,
32 OatQuickMethodHeader* dependent_header) {
33 auto it = cha_dependency_map_.find(method);
34 if (it == cha_dependency_map_.end()) {
35 cha_dependency_map_[method] =
36 new std::vector<std::pair<art::ArtMethod*, art::OatQuickMethodHeader*>>();
37 it = cha_dependency_map_.find(method);
38 } else {
39 DCHECK(it->second != nullptr);
40 }
41 it->second->push_back(std::make_pair(dependent_method, dependent_header));
42}
43
44std::vector<std::pair<ArtMethod*, OatQuickMethodHeader*>>*
45 ClassHierarchyAnalysis::GetDependents(ArtMethod* method) {
46 auto it = cha_dependency_map_.find(method);
47 if (it != cha_dependency_map_.end()) {
48 DCHECK(it->second != nullptr);
49 return it->second;
50 }
51 return nullptr;
52}
53
54void ClassHierarchyAnalysis::RemoveDependencyFor(ArtMethod* method) {
55 auto it = cha_dependency_map_.find(method);
56 if (it != cha_dependency_map_.end()) {
57 auto dependents = it->second;
58 cha_dependency_map_.erase(it);
59 delete dependents;
60 }
61}
62
63void ClassHierarchyAnalysis::RemoveDependentsWithMethodHeaders(
64 const std::unordered_set<OatQuickMethodHeader*>& method_headers) {
65 // Iterate through all entries in the dependency map and remove any entry that
66 // contains one of those in method_headers.
67 for (auto map_it = cha_dependency_map_.begin(); map_it != cha_dependency_map_.end(); ) {
68 auto dependents = map_it->second;
69 for (auto vec_it = dependents->begin(); vec_it != dependents->end(); ) {
70 OatQuickMethodHeader* method_header = vec_it->second;
71 auto it = std::find(method_headers.begin(), method_headers.end(), method_header);
72 if (it != method_headers.end()) {
73 vec_it = dependents->erase(vec_it);
74 } else {
75 vec_it++;
76 }
77 }
78 // Remove the map entry if there are no more dependents.
79 if (dependents->empty()) {
80 map_it = cha_dependency_map_.erase(map_it);
81 delete dependents;
82 } else {
83 map_it++;
84 }
85 }
86}
87
88// This stack visitor walks the stack and for compiled code with certain method
89// headers, sets the should_deoptimize flag on stack to 1.
90// TODO: also set the register value to 1 when should_deoptimize is allocated in
91// a register.
92class CHAStackVisitor FINAL : public StackVisitor {
93 public:
94 CHAStackVisitor(Thread* thread_in,
95 Context* context,
96 const std::unordered_set<OatQuickMethodHeader*>& method_headers)
97 : StackVisitor(thread_in, context, StackVisitor::StackWalkKind::kSkipInlinedFrames),
98 method_headers_(method_headers) {
99 }
100
101 bool VisitFrame() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
102 ArtMethod* method = GetMethod();
Mingyao Yang7b9a83f2016-12-13 12:28:31 -0800103 // Avoid types of methods that do not have an oat quick method header.
104 if (method == nullptr ||
105 method->IsRuntimeMethod() ||
106 method->IsNative() ||
107 method->IsProxyMethod()) {
Mingyao Yang063fc772016-08-02 11:02:54 -0700108 return true;
109 }
110 if (GetCurrentQuickFrame() == nullptr) {
111 // Not compiled code.
112 return true;
113 }
114 // Method may have multiple versions of compiled code. Check
115 // the method header to see if it has should_deoptimize flag.
116 const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
Mingyao Yang7b9a83f2016-12-13 12:28:31 -0800117 DCHECK(method_header != nullptr);
Mingyao Yang063fc772016-08-02 11:02:54 -0700118 if (!method_header->HasShouldDeoptimizeFlag()) {
119 // This compiled version doesn't have should_deoptimize flag. Skip.
120 return true;
121 }
122 auto it = std::find(method_headers_.begin(), method_headers_.end(), method_header);
123 if (it == method_headers_.end()) {
124 // Not in the list of method headers that should be deoptimized.
125 return true;
126 }
127
128 // The compiled code on stack is not valid anymore. Need to deoptimize.
129 SetShouldDeoptimizeFlag();
130
131 return true;
132 }
133
134 private:
135 void SetShouldDeoptimizeFlag() REQUIRES_SHARED(Locks::mutator_lock_) {
136 QuickMethodFrameInfo frame_info = GetCurrentQuickFrameInfo();
137 size_t frame_size = frame_info.FrameSizeInBytes();
138 uint8_t* sp = reinterpret_cast<uint8_t*>(GetCurrentQuickFrame());
139 size_t core_spill_size = POPCOUNT(frame_info.CoreSpillMask()) *
140 GetBytesPerGprSpillLocation(kRuntimeISA);
141 size_t fpu_spill_size = POPCOUNT(frame_info.FpSpillMask()) *
142 GetBytesPerFprSpillLocation(kRuntimeISA);
143 size_t offset = frame_size - core_spill_size - fpu_spill_size - kShouldDeoptimizeFlagSize;
144 uint8_t* should_deoptimize_addr = sp + offset;
145 // Set deoptimization flag to 1.
146 DCHECK(*should_deoptimize_addr == 0 || *should_deoptimize_addr == 1);
147 *should_deoptimize_addr = 1;
148 }
149
150 // Set of method headers for compiled code that should be deoptimized.
151 const std::unordered_set<OatQuickMethodHeader*>& method_headers_;
152
153 DISALLOW_COPY_AND_ASSIGN(CHAStackVisitor);
154};
155
156class CHACheckpoint FINAL : public Closure {
157 public:
158 explicit CHACheckpoint(const std::unordered_set<OatQuickMethodHeader*>& method_headers)
159 : barrier_(0),
160 method_headers_(method_headers) {}
161
162 void Run(Thread* thread) OVERRIDE {
163 // Note thread and self may not be equal if thread was already suspended at
164 // the point of the request.
165 Thread* self = Thread::Current();
166 ScopedObjectAccess soa(self);
167 CHAStackVisitor visitor(thread, nullptr, method_headers_);
168 visitor.WalkStack();
169 barrier_.Pass(self);
170 }
171
172 void WaitForThreadsToRunThroughCheckpoint(size_t threads_running_checkpoint) {
173 Thread* self = Thread::Current();
174 ScopedThreadStateChange tsc(self, kWaitingForCheckPointsToRun);
175 barrier_.Increment(self, threads_running_checkpoint);
176 }
177
178 private:
179 // The barrier to be passed through and for the requestor to wait upon.
180 Barrier barrier_;
181 // List of method headers for invalidated compiled code.
182 const std::unordered_set<OatQuickMethodHeader*>& method_headers_;
183
184 DISALLOW_COPY_AND_ASSIGN(CHACheckpoint);
185};
186
187void ClassHierarchyAnalysis::VerifyNonSingleImplementation(mirror::Class* verify_class,
Mingyao Yange8fcd012017-01-20 10:43:30 -0800188 uint16_t verify_index,
189 ArtMethod* excluded_method) {
Mingyao Yang063fc772016-08-02 11:02:54 -0700190 // Grab cha_lock_ to make sure all single-implementation updates are seen.
191 PointerSize image_pointer_size =
192 Runtime::Current()->GetClassLinker()->GetImagePointerSize();
193 MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
194 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) {
200 DCHECK(!verify_method->HasSingleImplementation())
201 << "class: " << verify_class->PrettyClass()
202 << " verify_method: " << verify_method->PrettyMethod(true);
203 if (verify_method->IsAbstract()) {
204 DCHECK(verify_method->GetSingleImplementation(image_pointer_size) == nullptr);
205 }
206 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700207 verify_class = verify_class->GetSuperClass();
208 }
209}
210
211void ClassHierarchyAnalysis::CheckSingleImplementationInfo(
212 Handle<mirror::Class> klass,
213 ArtMethod* virtual_method,
214 ArtMethod* method_in_super,
Mingyao Yange8fcd012017-01-20 10:43:30 -0800215 std::unordered_set<ArtMethod*>& invalidated_single_impl_methods,
216 PointerSize pointer_size) {
Mingyao Yang063fc772016-08-02 11:02:54 -0700217 // TODO: if klass is not instantiable, virtual_method isn't invocable yet so
218 // even if it overrides, it doesn't invalidate single-implementation
219 // assumption.
220
Mingyao Yange8fcd012017-01-20 10:43:30 -0800221 DCHECK((virtual_method != method_in_super) || virtual_method->IsAbstract());
Mingyao Yang063fc772016-08-02 11:02:54 -0700222 DCHECK(method_in_super->GetDeclaringClass()->IsResolved()) << "class isn't resolved";
223 // If virtual_method doesn't come from a default interface method, it should
224 // be supplied by klass.
Mingyao Yange8fcd012017-01-20 10:43:30 -0800225 DCHECK(virtual_method == method_in_super ||
226 virtual_method->IsCopied() ||
Mingyao Yang063fc772016-08-02 11:02:54 -0700227 virtual_method->GetDeclaringClass() == klass.Get());
228
Mingyao Yange8fcd012017-01-20 10:43:30 -0800229 // To make updating single-implementation flags simple, we always maintain the following
230 // invariant:
231 // Say all virtual methods in the same vtable slot, starting from the bottom child class
232 // to super classes, is a sequence of unique methods m3, m2, m1, ... (after removing duplicate
233 // methods for inherited methods).
234 // For example for the following class hierarchy,
235 // class A { void m() { ... } }
236 // class B extends A { void m() { ... } }
237 // class C extends B {}
238 // class D extends C { void m() { ... } }
239 // the sequence is D.m(), B.m(), A.m().
240 // The single-implementation status for that sequence of methods begin with one or two true's,
241 // then become all falses. The only case where two true's are possible is for one abstract
242 // method m and one non-abstract method mImpl that overrides method m.
243 // With the invariant, when linking in a new class, we only need to at most update one or
244 // two methods in the sequence for their single-implementation status, in order to maintain
245 // the invariant.
246
Mingyao Yang063fc772016-08-02 11:02:54 -0700247 if (!method_in_super->HasSingleImplementation()) {
248 // method_in_super already has multiple implementations. All methods in the
249 // same vtable slots in its super classes should have
250 // non-single-implementation already.
251 if (kIsDebugBuild) {
252 VerifyNonSingleImplementation(klass->GetSuperClass()->GetSuperClass(),
Mingyao Yange8fcd012017-01-20 10:43:30 -0800253 method_in_super->GetMethodIndex(),
254 nullptr /* excluded_method */);
Mingyao Yang063fc772016-08-02 11:02:54 -0700255 }
256 return;
257 }
258
259 // Native methods don't have single-implementation flag set.
260 DCHECK(!method_in_super->IsNative());
Mingyao Yange8fcd012017-01-20 10:43:30 -0800261
262 uint16_t method_index = method_in_super->GetMethodIndex();
263 if (method_in_super->IsAbstract()) {
264 if (kIsDebugBuild) {
265 // An abstract method should have made all methods in the same vtable
266 // slot above it in the class hierarchy having non-single-implementation.
267 mirror::Class* super_super = klass->GetSuperClass()->GetSuperClass();
268 VerifyNonSingleImplementation(super_super,
269 method_index,
270 method_in_super);
271 }
272
273 if (virtual_method->IsAbstract()) {
274 // SUPER: abstract, VIRTUAL: abstract.
275 if (method_in_super == virtual_method) {
276 DCHECK(klass->IsInstantiable());
277 // An instantiable subclass hasn't provided a concrete implementation of
278 // the abstract method. Invoking method_in_super may throw AbstractMethodError.
279 // This is an uncommon case, so we simply treat method_in_super as not
280 // having single-implementation.
281 invalidated_single_impl_methods.insert(method_in_super);
282 return;
283 } else {
284 // One abstract method overrides another abstract method. This is an uncommon
285 // case. We simply treat method_in_super as not having single-implementation.
286 invalidated_single_impl_methods.insert(method_in_super);
287 return;
288 }
289 } else {
290 // SUPER: abstract, VIRTUAL: non-abstract.
291 // A non-abstract method overrides an abstract method.
292 if (method_in_super->GetSingleImplementation(pointer_size) == nullptr) {
293 // Abstract method_in_super has no implementation yet.
294 // We need to grab cha_lock_ for further checking/updating due to possible
295 // races.
296 MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
297 if (!method_in_super->HasSingleImplementation()) {
298 return;
299 }
300 if (method_in_super->GetSingleImplementation(pointer_size) == nullptr) {
301 // virtual_method becomes the first implementation for method_in_super.
302 method_in_super->SetSingleImplementation(virtual_method, pointer_size);
303 // Keep method_in_super's single-implementation status.
304 return;
305 }
306 // Fall through to invalidate method_in_super's single-implementation status.
307 }
308 // Abstract method_in_super already got one implementation.
309 // Invalidate method_in_super's single-implementation status.
310 invalidated_single_impl_methods.insert(method_in_super);
311 return;
312 }
313 } else {
314 if (virtual_method->IsAbstract()) {
315 // SUPER: non-abstract, VIRTUAL: abstract.
316 // An abstract method overrides a non-abstract method. This is an uncommon
317 // case, we simply treat both methods as not having single-implementation.
318 invalidated_single_impl_methods.insert(virtual_method);
319 // Fall-through to handle invalidating method_in_super of its
320 // single-implementation status.
321 }
322
323 // SUPER: non-abstract, VIRTUAL: non-abstract/abstract(fall-through from previous if).
324 // Invalidate method_in_super's single-implementation status.
325 invalidated_single_impl_methods.insert(method_in_super);
326
327 // method_in_super might be the single-implementation of another abstract method,
328 // which should be also invalidated of its single-implementation status.
329 mirror::Class* super_super = klass->GetSuperClass()->GetSuperClass();
330 while (super_super != nullptr &&
331 method_index < super_super->GetVTableLength()) {
332 ArtMethod* method_in_super_super = super_super->GetVTableEntry(method_index, pointer_size);
333 if (method_in_super_super != method_in_super) {
334 if (method_in_super_super->IsAbstract()) {
335 if (method_in_super_super->HasSingleImplementation()) {
336 // Invalidate method_in_super's single-implementation status.
337 invalidated_single_impl_methods.insert(method_in_super_super);
338 // No need to further traverse up the class hierarchy since if there
339 // are cases that one abstract method overrides another method, we
340 // should have made that method having non-single-implementation already.
341 } else {
342 // method_in_super_super is already non-single-implementation.
343 // No need to further traverse up the class hierarchy.
344 }
345 } else {
346 DCHECK(!method_in_super_super->HasSingleImplementation());
347 // No need to further traverse up the class hierarchy since two non-abstract
348 // methods (method_in_super and method_in_super_super) should have set all
349 // other methods (abstract or not) in the vtable slot to be non-single-implementation.
350 }
351
352 if (kIsDebugBuild) {
353 VerifyNonSingleImplementation(super_super->GetSuperClass(),
354 method_index,
355 method_in_super_super);
356 }
357 // No need to go any further.
358 return;
359 } else {
360 super_super = super_super->GetSuperClass();
361 }
362 }
363 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700364}
365
366void ClassHierarchyAnalysis::InitSingleImplementationFlag(Handle<mirror::Class> klass,
Mingyao Yange8fcd012017-01-20 10:43:30 -0800367 ArtMethod* method,
368 PointerSize pointer_size) {
Mingyao Yang063fc772016-08-02 11:02:54 -0700369 DCHECK(method->IsCopied() || method->GetDeclaringClass() == klass.Get());
370 if (klass->IsFinal() || method->IsFinal()) {
371 // Final classes or methods do not need CHA for devirtualization.
372 // This frees up modifier bits for intrinsics which currently are only
373 // used for static methods or methods of final classes.
374 return;
375 }
376 if (method->IsNative()) {
377 // Native method's invocation overhead is already high and it
378 // cannot be inlined. It's not worthwhile to devirtualize the
379 // call which can add a deoptimization point.
380 DCHECK(!method->HasSingleImplementation());
Mingyao Yange8fcd012017-01-20 10:43:30 -0800381 } else if (method->IsAbstract()) {
382 if (method->GetDeclaringClass()->IsInstantiable()) {
383 // Rare case, but we do accept it (such as 800-smali/smali/b_26143249.smali).
384 // Do not attempt to devirtualize it.
385 method->SetHasSingleImplementation(false);
386 } else {
387 // Abstract method starts with single-implementation flag set and null
388 // implementation method.
389 method->SetHasSingleImplementation(true);
390 DCHECK(method->GetSingleImplementation(pointer_size) == nullptr);
391 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700392 } else {
393 method->SetHasSingleImplementation(true);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800394 // Single implementation of non-abstract method is itself.
395 DCHECK_EQ(method->GetSingleImplementation(pointer_size), method);
Mingyao Yang063fc772016-08-02 11:02:54 -0700396 }
397}
398
399void ClassHierarchyAnalysis::UpdateAfterLoadingOf(Handle<mirror::Class> klass) {
400 if (klass->IsInterface()) {
401 return;
402 }
403 mirror::Class* super_class = klass->GetSuperClass();
404 if (super_class == nullptr) {
405 return;
406 }
407
408 // Keeps track of all methods whose single-implementation assumption
409 // is invalidated by linking `klass`.
410 std::unordered_set<ArtMethod*> invalidated_single_impl_methods;
411
412 PointerSize image_pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
413 // Do an entry-by-entry comparison of vtable contents with super's vtable.
414 for (int32_t i = 0; i < super_class->GetVTableLength(); ++i) {
415 ArtMethod* method = klass->GetVTableEntry(i, image_pointer_size);
416 ArtMethod* method_in_super = super_class->GetVTableEntry(i, image_pointer_size);
417 if (method == method_in_super) {
418 // vtable slot entry is inherited from super class.
Mingyao Yange8fcd012017-01-20 10:43:30 -0800419 if (method->IsAbstract() && klass->IsInstantiable()) {
420 // An instantiable class that inherits an abstract method is treated as
421 // supplying an implementation that throws AbstractMethodError.
422 CheckSingleImplementationInfo(klass,
423 method,
424 method_in_super,
425 invalidated_single_impl_methods,
426 image_pointer_size);
427 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700428 continue;
429 }
Mingyao Yange8fcd012017-01-20 10:43:30 -0800430 InitSingleImplementationFlag(klass, method, image_pointer_size);
Mingyao Yang063fc772016-08-02 11:02:54 -0700431 CheckSingleImplementationInfo(klass,
432 method,
433 method_in_super,
Mingyao Yange8fcd012017-01-20 10:43:30 -0800434 invalidated_single_impl_methods,
435 image_pointer_size);
Mingyao Yang063fc772016-08-02 11:02:54 -0700436 }
437
438 // For new virtual methods that don't override.
439 for (int32_t i = super_class->GetVTableLength(); i < klass->GetVTableLength(); ++i) {
440 ArtMethod* method = klass->GetVTableEntry(i, image_pointer_size);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800441 InitSingleImplementationFlag(klass, method, image_pointer_size);
Mingyao Yang063fc772016-08-02 11:02:54 -0700442 }
443
444 Runtime* const runtime = Runtime::Current();
445 if (!invalidated_single_impl_methods.empty()) {
446 Thread *self = Thread::Current();
447 // Method headers for compiled code to be invalidated.
448 std::unordered_set<OatQuickMethodHeader*> dependent_method_headers;
449
450 {
451 // We do this under cha_lock_. Committing code also grabs this lock to
452 // make sure the code is only committed when all single-implementation
453 // assumptions are still true.
454 MutexLock cha_mu(self, *Locks::cha_lock_);
455 // Invalidate compiled methods that assume some virtual calls have only
456 // single implementations.
457 for (ArtMethod* invalidated : invalidated_single_impl_methods) {
458 if (!invalidated->HasSingleImplementation()) {
459 // It might have been invalidated already when other class linking is
460 // going on.
461 continue;
462 }
463 invalidated->SetHasSingleImplementation(false);
Mingyao Yange8fcd012017-01-20 10:43:30 -0800464 if (invalidated->IsAbstract()) {
465 // Clear the single implementation method.
466 invalidated->SetSingleImplementation(nullptr, image_pointer_size);
467 }
Mingyao Yang063fc772016-08-02 11:02:54 -0700468
469 if (runtime->IsAotCompiler()) {
470 // No need to invalidate any compiled code as the AotCompiler doesn't
471 // run any code.
472 continue;
473 }
474
475 // Invalidate all dependents.
476 auto dependents = GetDependents(invalidated);
477 if (dependents == nullptr) {
478 continue;
479 }
480 for (const auto& dependent : *dependents) {
481 ArtMethod* method = dependent.first;;
482 OatQuickMethodHeader* method_header = dependent.second;
483 VLOG(class_linker) << "CHA invalidated compiled code for " << method->PrettyMethod();
484 DCHECK(runtime->UseJitCompilation());
485 runtime->GetJit()->GetCodeCache()->InvalidateCompiledCodeFor(
486 method, method_header);
487 dependent_method_headers.insert(method_header);
488 }
489 RemoveDependencyFor(invalidated);
490 }
491 }
492
493 if (dependent_method_headers.empty()) {
494 return;
495 }
496 // Deoptimze compiled code on stack that should have been invalidated.
497 CHACheckpoint checkpoint(dependent_method_headers);
498 size_t threads_running_checkpoint = runtime->GetThreadList()->RunCheckpoint(&checkpoint);
499 if (threads_running_checkpoint != 0) {
500 checkpoint.WaitForThreadsToRunThroughCheckpoint(threads_running_checkpoint);
501 }
502 }
503}
504
505} // namespace art