blob: 81fe63777f4980a210472164fd1c7fa7aefca287 [file] [log] [blame]
jeffhao725a9572012-11-13 18:20:12 -08001/*
2 * Copyright (C) 2011 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 "instrumentation.h"
18
19#include <sys/uio.h>
20
Elliott Hughes76160052012-12-12 16:31:20 -080021#include "base/unix_file/fd_file.h"
jeffhao725a9572012-11-13 18:20:12 -080022#include "class_linker.h"
23#include "debugger.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080024#include "mirror/class-inl.h"
25#include "mirror/dex_cache.h"
26#include "mirror/abstract_method-inl.h"
27#include "mirror/object_array-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070028#include "mirror/object-inl.h"
Ian Rogersc928de92013-02-27 14:30:44 -080029#if !defined(ART_USE_PORTABLE_COMPILER)
jeffhao725a9572012-11-13 18:20:12 -080030#include "oat/runtime/oat_support_entrypoints.h"
31#endif
32#include "object_utils.h"
33#include "os.h"
34#include "scoped_thread_state_change.h"
35#include "thread.h"
36#include "thread_list.h"
37#include "trace.h"
38
39namespace art {
40
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080041static bool InstallStubsClassVisitor(mirror::Class* klass, void*)
jeffhao725a9572012-11-13 18:20:12 -080042 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
43 Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
44 for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080045 mirror::AbstractMethod* method = klass->GetDirectMethod(i);
jeffhao725a9572012-11-13 18:20:12 -080046 if (instrumentation->GetSavedCodeFromMap(method) == NULL) {
47 instrumentation->SaveAndUpdateCode(method);
48 }
49 }
50
51 for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080052 mirror::AbstractMethod* method = klass->GetVirtualMethod(i);
jeffhao725a9572012-11-13 18:20:12 -080053 if (instrumentation->GetSavedCodeFromMap(method) == NULL) {
54 instrumentation->SaveAndUpdateCode(method);
55 }
56 }
57 return true;
58}
59
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080060static bool UninstallStubsClassVisitor(mirror::Class* klass, void*)
jeffhao725a9572012-11-13 18:20:12 -080061 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
62 Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
63 for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080064 mirror::AbstractMethod* method = klass->GetDirectMethod(i);
jeffhao725a9572012-11-13 18:20:12 -080065 if (instrumentation->GetSavedCodeFromMap(method) != NULL) {
66 instrumentation->ResetSavedCode(method);
67 }
68 }
69
70 for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080071 mirror::AbstractMethod* method = klass->GetVirtualMethod(i);
jeffhao725a9572012-11-13 18:20:12 -080072 if (instrumentation->GetSavedCodeFromMap(method) != NULL) {
73 instrumentation->ResetSavedCode(method);
74 }
75 }
76 return true;
77}
78
Ian Rogers306057f2012-11-26 12:45:53 -080079void InstrumentationInstallStack(Thread* self, void* arg)
80 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
81 struct InstallStackVisitor : public StackVisitor {
82 InstallStackVisitor(Thread* self, uintptr_t instrumentation_exit_pc)
Ian Rogers7a22fa62013-01-23 12:16:16 -080083 : StackVisitor(self, NULL), self_(self),
84 instrumentation_exit_pc_(instrumentation_exit_pc) {}
jeffhao725a9572012-11-13 18:20:12 -080085
Ian Rogers306057f2012-11-26 12:45:53 -080086 virtual bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
87 if (GetCurrentQuickFrame() == NULL) {
88 return true; // Ignore shadow frames.
89 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080090 mirror::AbstractMethod* m = GetMethod();
Ian Rogers306057f2012-11-26 12:45:53 -080091 if (m == NULL) {
92 return true; // Ignore upcalls.
93 }
94 if (m->GetDexMethodIndex() == DexFile::kDexNoIndex16) {
95 return true; // Ignore unresolved methods since they will be instrumented after resolution.
96 }
97 uintptr_t pc = GetReturnPc();
98 InstrumentationStackFrame instrumentation_frame(m, pc, GetFrameId());
99 self_->PushBackInstrumentationStackFrame(instrumentation_frame);
100 SetReturnPc(instrumentation_exit_pc_);
101 return true; // Continue.
102 }
103 Thread* const self_;
104 const uintptr_t instrumentation_exit_pc_;
105 };
106 uintptr_t instrumentation_exit_pc = GetInstrumentationExitPc();
107 InstallStackVisitor visitor(self, instrumentation_exit_pc);
108 visitor.WalkStack(true);
109 Trace* trace = reinterpret_cast<Trace*>(arg);
110 if (trace != NULL) {
111 std::deque<InstrumentationStackFrame>::const_reverse_iterator it =
112 self->GetInstrumentationStack()->rbegin();
113 std::deque<InstrumentationStackFrame>::const_reverse_iterator end =
114 self->GetInstrumentationStack()->rend();
115 for (; it != end; ++it) {
116 trace->LogMethodTraceEvent(self, (*it).method_, Trace::kMethodTraceEnter);
117 }
118 }
119}
120
121static void InstrumentationRestoreStack(Thread* self, void*)
122 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
123 struct RestoreStackVisitor : public StackVisitor {
124 RestoreStackVisitor(Thread* self, uintptr_t instrumentation_exit_pc)
Ian Rogers7a22fa62013-01-23 12:16:16 -0800125 : StackVisitor(self, NULL), self_(self),
126 instrumentation_exit_pc_(instrumentation_exit_pc) {}
Ian Rogers306057f2012-11-26 12:45:53 -0800127
128 virtual bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
jeffhao725a9572012-11-13 18:20:12 -0800129 if (self_->IsInstrumentationStackEmpty()) {
130 return false; // Stop.
131 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800132 mirror::AbstractMethod* m = GetMethod();
Ian Rogers306057f2012-11-26 12:45:53 -0800133 if (m == NULL) {
134 return true; // Ignore upcalls.
135 }
jeffhao725a9572012-11-13 18:20:12 -0800136 uintptr_t pc = GetReturnPc();
Ian Rogers306057f2012-11-26 12:45:53 -0800137 if (pc == instrumentation_exit_pc_) {
jeffhao725a9572012-11-13 18:20:12 -0800138 InstrumentationStackFrame instrumentation_frame = self_->PopInstrumentationStackFrame();
139 SetReturnPc(instrumentation_frame.return_pc_);
Ian Rogers306057f2012-11-26 12:45:53 -0800140 CHECK(m == instrumentation_frame.method_);
141 CHECK_EQ(GetFrameId(), instrumentation_frame.frame_id_);
142 Runtime* runtime = Runtime::Current();
143 if (runtime->IsMethodTracingActive()) {
144 Trace* trace = runtime->GetInstrumentation()->GetTrace();
145 trace->LogMethodTraceEvent(self_, m, Trace::kMethodTraceExit);
146 }
jeffhao725a9572012-11-13 18:20:12 -0800147 }
148 return true; // Continue.
149 }
Ian Rogers306057f2012-11-26 12:45:53 -0800150 Thread* const self_;
151 const uintptr_t instrumentation_exit_pc_;
jeffhao725a9572012-11-13 18:20:12 -0800152 };
Ian Rogers306057f2012-11-26 12:45:53 -0800153 uintptr_t instrumentation_exit_pc = GetInstrumentationExitPc();
154 RestoreStackVisitor visitor(self, instrumentation_exit_pc);
155 visitor.WalkStack(true);
jeffhao725a9572012-11-13 18:20:12 -0800156}
157
158Instrumentation::~Instrumentation() {
159 delete trace_;
160}
161
162void Instrumentation::InstallStubs() {
Ian Rogers306057f2012-11-26 12:45:53 -0800163 Thread* self = Thread::Current();
164 Locks::thread_list_lock_->AssertNotHeld(self);
jeffhao725a9572012-11-13 18:20:12 -0800165 Runtime::Current()->GetClassLinker()->VisitClasses(InstallStubsClassVisitor, NULL);
Ian Rogers306057f2012-11-26 12:45:53 -0800166 MutexLock mu(self, *Locks::thread_list_lock_);
167 Runtime::Current()->GetThreadList()->ForEach(InstrumentationInstallStack, GetTrace());
jeffhao725a9572012-11-13 18:20:12 -0800168}
169
170void Instrumentation::UninstallStubs() {
171 Thread* self = Thread::Current();
172 Locks::thread_list_lock_->AssertNotHeld(self);
173 Runtime::Current()->GetClassLinker()->VisitClasses(UninstallStubsClassVisitor, NULL);
174 MutexLock mu(self, *Locks::thread_list_lock_);
175 Runtime::Current()->GetThreadList()->ForEach(InstrumentationRestoreStack, NULL);
176}
177
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800178void Instrumentation::AddSavedCodeToMap(const mirror::AbstractMethod* method, const void* code) {
jeffhao725a9572012-11-13 18:20:12 -0800179 saved_code_map_.Put(method, code);
180}
181
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800182void Instrumentation::RemoveSavedCodeFromMap(const mirror::AbstractMethod* method) {
jeffhao725a9572012-11-13 18:20:12 -0800183 saved_code_map_.erase(method);
184}
185
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800186const void* Instrumentation::GetSavedCodeFromMap(const mirror::AbstractMethod* method) {
187 typedef SafeMap<const mirror::AbstractMethod*, const void*>::const_iterator It; // TODO: C++0x auto
jeffhao725a9572012-11-13 18:20:12 -0800188 It it = saved_code_map_.find(method);
189 if (it == saved_code_map_.end()) {
190 return NULL;
191 } else {
192 return it->second;
193 }
194}
195
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800196void Instrumentation::SaveAndUpdateCode(mirror::AbstractMethod* method) {
Ian Rogersc928de92013-02-27 14:30:44 -0800197#if defined(ART_USE_PORTABLE_COMPILER)
jeffhao725a9572012-11-13 18:20:12 -0800198 UNUSED(method);
199 UNIMPLEMENTED(FATAL);
200#else
201 void* instrumentation_stub = GetInstrumentationEntryPoint();
202 CHECK(GetSavedCodeFromMap(method) == NULL);
203 AddSavedCodeToMap(method, method->GetCode());
204 method->SetCode(instrumentation_stub);
205#endif
206}
207
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800208void Instrumentation::ResetSavedCode(mirror::AbstractMethod* method) {
jeffhao725a9572012-11-13 18:20:12 -0800209 CHECK(GetSavedCodeFromMap(method) != NULL);
210 method->SetCode(GetSavedCodeFromMap(method));
211 RemoveSavedCodeFromMap(method);
212}
213
214Trace* Instrumentation::GetTrace() const {
215 return trace_;
216}
217
218void Instrumentation::SetTrace(Trace* trace) {
219 trace_ = trace;
220}
221
222void Instrumentation::RemoveTrace() {
223 delete trace_;
224 trace_ = NULL;
225}
226
227uint32_t InstrumentationMethodUnwindFromCode(Thread* self) {
228 Trace* trace = Runtime::Current()->GetInstrumentation()->GetTrace();
229 InstrumentationStackFrame instrumentation_frame = self->PopInstrumentationStackFrame();
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800230 mirror::AbstractMethod* method = instrumentation_frame.method_;
jeffhao725a9572012-11-13 18:20:12 -0800231 uint32_t lr = instrumentation_frame.return_pc_;
232
233 trace->LogMethodTraceEvent(self, method, Trace::kMethodTraceUnwind);
234
235 return lr;
236}
237
238} // namespace art