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 kWaiting:
51       case kTimedWaiting:
52         VisitWaitingObject(monitor_object, state);
53         break;
54       case kSleeping:
55         VisitSleepingObject(monitor_object);
56         break;
57 
58       case kBlocked:
59       case 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