1 /*
2 * Copyright (C) 2014 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 "monitor_objects_stack_visitor.h"
18
19 #include "obj_ptr-inl.h"
20 #include "read_barrier-inl.h"
21 #include "thread-current-inl.h"
22
23 namespace art {
24
VisitFrame()25 bool MonitorObjectsStackVisitor::VisitFrame() {
26 ArtMethod* m = GetMethod();
27 if (m->IsRuntimeMethod()) {
28 return true;
29 }
30
31 VisitMethodResult vmrEntry = StartMethod(m, frame_count);
32 switch (vmrEntry) {
33 case VisitMethodResult::kContinueMethod:
34 break;
35 case VisitMethodResult::kSkipMethod:
36 return true;
37 case VisitMethodResult::kEndStackWalk:
38 return false;
39 }
40
41 if (frame_count == 0) {
42 // Top frame, check for blocked state.
43
44 ObjPtr<mirror::Object> monitor_object;
45 uint32_t lock_owner_tid;
46 ThreadState state = Monitor::FetchState(GetThread(),
47 &monitor_object,
48 &lock_owner_tid);
49 switch (state) {
50 case ThreadState::kWaiting:
51 case ThreadState::kTimedWaiting:
52 VisitWaitingObject(monitor_object, state);
53 break;
54 case ThreadState::kSleeping:
55 VisitSleepingObject(monitor_object);
56 break;
57
58 case ThreadState::kBlocked:
59 case ThreadState::kWaitingForLockInflation:
60 VisitBlockedOnObject(monitor_object, state, lock_owner_tid);
61 break;
62
63 default:
64 break;
65 }
66 }
67
68 if (dump_locks) {
69 // Visit locks, but do not abort on errors. This could trigger a nested abort.
70 // Skip visiting locks if dump_locks is false as it would cause a bad_mutexes_held in
71 // RegTypeCache::RegTypeCache due to thread_list_lock.
72 Monitor::VisitLocks(this, VisitLockedObject, this, false);
73 }
74
75 ++frame_count;
76
77 VisitMethodResult vmrExit = EndMethod(m);
78 switch (vmrExit) {
79 case VisitMethodResult::kContinueMethod:
80 case VisitMethodResult::kSkipMethod:
81 return true;
82
83 case VisitMethodResult::kEndStackWalk:
84 return false;
85 }
86 LOG(FATAL) << "Unreachable";
87 UNREACHABLE();
88 }
89
VisitLockedObject(ObjPtr<mirror::Object> o,void * context)90 void MonitorObjectsStackVisitor::VisitLockedObject(ObjPtr<mirror::Object> o, void* context) {
91 MonitorObjectsStackVisitor* self = reinterpret_cast<MonitorObjectsStackVisitor*>(context);
92 if (o != nullptr) {
93 if (kUseReadBarrier && Thread::Current()->GetIsGcMarking()) {
94 // We may call Thread::Dump() in the middle of the CC thread flip and this thread's stack
95 // may have not been flipped yet and "o" may be a from-space (stale) ref, in which case the
96 // IdentityHashCode call below will crash. So explicitly mark/forward it here.
97 o = ReadBarrier::Mark(o.Ptr());
98 }
99 }
100 self->VisitLockedObject(o);
101 }
102
103 } // namespace art
104