blob: d796aef7f01392eeba81438743994616d6aa5c66 [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
21#include "class_linker.h"
22#include "debugger.h"
23#include "dex_cache.h"
24#if !defined(ART_USE_LLVM_COMPILER)
25#include "oat/runtime/oat_support_entrypoints.h"
26#endif
27#include "object_utils.h"
28#include "os.h"
29#include "scoped_thread_state_change.h"
30#include "thread.h"
31#include "thread_list.h"
32#include "trace.h"
33
34namespace art {
35
36static bool InstallStubsClassVisitor(Class* klass, void*)
37 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
38 Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
39 for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
40 AbstractMethod* method = klass->GetDirectMethod(i);
41 if (instrumentation->GetSavedCodeFromMap(method) == NULL) {
42 instrumentation->SaveAndUpdateCode(method);
43 }
44 }
45
46 for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
47 AbstractMethod* method = klass->GetVirtualMethod(i);
48 if (instrumentation->GetSavedCodeFromMap(method) == NULL) {
49 instrumentation->SaveAndUpdateCode(method);
50 }
51 }
52 return true;
53}
54
55static bool UninstallStubsClassVisitor(Class* klass, void*)
56 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
57 Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
58 for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
59 AbstractMethod* method = klass->GetDirectMethod(i);
60 if (instrumentation->GetSavedCodeFromMap(method) != NULL) {
61 instrumentation->ResetSavedCode(method);
62 }
63 }
64
65 for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
66 AbstractMethod* method = klass->GetVirtualMethod(i);
67 if (instrumentation->GetSavedCodeFromMap(method) != NULL) {
68 instrumentation->ResetSavedCode(method);
69 }
70 }
71 return true;
72}
73
74static void InstrumentationRestoreStack(Thread* self, void*) NO_THREAD_SAFETY_ANALYSIS {
75 struct RestoreStackVisitor : public StackVisitor {
76 RestoreStackVisitor(Thread* self)
77 : StackVisitor(self->GetManagedStack(), self->GetInstrumentationStack(), NULL), self_(self) {}
78
79 virtual bool VisitFrame() {
80 if (self_->IsInstrumentationStackEmpty()) {
81 return false; // Stop.
82 }
83 uintptr_t pc = GetReturnPc();
84 if (IsInstrumentationExitPc(pc)) {
85 InstrumentationStackFrame instrumentation_frame = self_->PopInstrumentationStackFrame();
86 SetReturnPc(instrumentation_frame.return_pc_);
87 CHECK(GetMethod() == instrumentation_frame.method_);
88 }
89 return true; // Continue.
90 }
91
92 Thread* self_;
93 };
94 RestoreStackVisitor visitor(self);
95 visitor.WalkStack();
96}
97
98Instrumentation::~Instrumentation() {
99 delete trace_;
100}
101
102void Instrumentation::InstallStubs() {
103 Runtime::Current()->GetClassLinker()->VisitClasses(InstallStubsClassVisitor, NULL);
104}
105
106void Instrumentation::UninstallStubs() {
107 Thread* self = Thread::Current();
108 Locks::thread_list_lock_->AssertNotHeld(self);
109 Runtime::Current()->GetClassLinker()->VisitClasses(UninstallStubsClassVisitor, NULL);
110 MutexLock mu(self, *Locks::thread_list_lock_);
111 Runtime::Current()->GetThreadList()->ForEach(InstrumentationRestoreStack, NULL);
112}
113
114void Instrumentation::AddSavedCodeToMap(const AbstractMethod* method, const void* code) {
115 saved_code_map_.Put(method, code);
116}
117
118void Instrumentation::RemoveSavedCodeFromMap(const AbstractMethod* method) {
119 saved_code_map_.erase(method);
120}
121
122const void* Instrumentation::GetSavedCodeFromMap(const AbstractMethod* method) {
123 typedef SafeMap<const AbstractMethod*, const void*>::const_iterator It; // TODO: C++0x auto
124 It it = saved_code_map_.find(method);
125 if (it == saved_code_map_.end()) {
126 return NULL;
127 } else {
128 return it->second;
129 }
130}
131
132void Instrumentation::SaveAndUpdateCode(AbstractMethod* method) {
133#if defined(ART_USE_LLVM_COMPILER)
134 UNUSED(method);
135 UNIMPLEMENTED(FATAL);
136#else
137 void* instrumentation_stub = GetInstrumentationEntryPoint();
138 CHECK(GetSavedCodeFromMap(method) == NULL);
139 AddSavedCodeToMap(method, method->GetCode());
140 method->SetCode(instrumentation_stub);
141#endif
142}
143
144void Instrumentation::ResetSavedCode(AbstractMethod* method) {
145 CHECK(GetSavedCodeFromMap(method) != NULL);
146 method->SetCode(GetSavedCodeFromMap(method));
147 RemoveSavedCodeFromMap(method);
148}
149
150Trace* Instrumentation::GetTrace() const {
151 return trace_;
152}
153
154void Instrumentation::SetTrace(Trace* trace) {
155 trace_ = trace;
156}
157
158void Instrumentation::RemoveTrace() {
159 delete trace_;
160 trace_ = NULL;
161}
162
163uint32_t InstrumentationMethodUnwindFromCode(Thread* self) {
164 Trace* trace = Runtime::Current()->GetInstrumentation()->GetTrace();
165 InstrumentationStackFrame instrumentation_frame = self->PopInstrumentationStackFrame();
166 AbstractMethod* method = instrumentation_frame.method_;
167 uint32_t lr = instrumentation_frame.return_pc_;
168
169 trace->LogMethodTraceEvent(self, method, Trace::kMethodTraceUnwind);
170
171 return lr;
172}
173
174} // namespace art