blob: a054462b2cf96d584043db58d26472218697de1a [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
Ian Rogersc7dd2952014-10-21 23:31:19 -070021#include <sstream>
22
Ian Rogerse63db272014-07-15 15:36:11 -070023#include "arch/context.h"
Ian Rogersef7d42f2014-01-06 12:55:46 -080024#include "atomic.h"
Elliott Hughes76160052012-12-12 16:31:20 -080025#include "base/unix_file/fd_file.h"
jeffhao725a9572012-11-13 18:20:12 -080026#include "class_linker.h"
27#include "debugger.h"
Ian Rogers62d6c772013-02-27 08:32:07 -080028#include "dex_file-inl.h"
Ian Rogersc7dd2952014-10-21 23:31:19 -070029#include "entrypoints/quick/quick_entrypoints.h"
Mathieu Chartierd8891782014-03-02 13:28:37 -080030#include "entrypoints/quick/quick_alloc_entrypoints.h"
Ian Rogers6f3dbba2014-10-14 17:41:57 -070031#include "entrypoints/runtime_asm_entrypoints.h"
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -070032#include "gc_root-inl.h"
Sebastien Hertz138dbfc2013-12-04 18:15:25 +010033#include "interpreter/interpreter.h"
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080034#include "jit/jit.h"
35#include "jit/jit_code_cache.h"
Brian Carlstromea46f952013-07-30 01:26:50 -070036#include "mirror/art_method-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080037#include "mirror/class-inl.h"
38#include "mirror/dex_cache.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080039#include "mirror/object_array-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070040#include "mirror/object-inl.h"
Ian Rogers62d6c772013-02-27 08:32:07 -080041#include "nth_caller_visitor.h"
jeffhao725a9572012-11-13 18:20:12 -080042#include "os.h"
43#include "scoped_thread_state_change.h"
44#include "thread.h"
45#include "thread_list.h"
jeffhao725a9572012-11-13 18:20:12 -080046
47namespace art {
Ian Rogersfa824272013-11-05 16:12:57 -080048
Ian Rogers62d6c772013-02-27 08:32:07 -080049namespace instrumentation {
jeffhao725a9572012-11-13 18:20:12 -080050
Sebastien Hertz5bfd5c92013-11-15 11:36:07 +010051const bool kVerboseInstrumentation = false;
52
Ian Rogers816432e2013-09-06 15:47:45 -070053// Do we want to deoptimize for method entry and exit listeners or just try to intercept
54// invocations? Deoptimization forces all code to run in the interpreter and considerably hurts the
55// application's performance.
Jeff Haobc678bb2014-08-11 18:00:29 -070056static constexpr bool kDeoptimizeForAccurateMethodEntryExitListeners = true;
Ian Rogers816432e2013-09-06 15:47:45 -070057
Ian Rogers62d6c772013-02-27 08:32:07 -080058static bool InstallStubsClassVisitor(mirror::Class* klass, void* arg)
Sebastien Hertza8a697f2015-01-15 12:28:47 +010059 EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers62d6c772013-02-27 08:32:07 -080060 Instrumentation* instrumentation = reinterpret_cast<Instrumentation*>(arg);
Sebastien Hertza10aa372015-01-21 17:30:58 +010061 instrumentation->InstallStubsForClass(klass);
62 return true; // we visit all classes.
Ian Rogers62d6c772013-02-27 08:32:07 -080063}
64
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -070065Instrumentation::Instrumentation()
66 : instrumentation_stubs_installed_(false), entry_exit_stubs_installed_(false),
67 interpreter_stubs_installed_(false),
68 interpret_only_(false), forced_interpret_only_(false),
69 have_method_entry_listeners_(false), have_method_exit_listeners_(false),
70 have_method_unwind_listeners_(false), have_dex_pc_listeners_(false),
Sebastien Hertz3f52eaf2014-04-04 17:50:18 +020071 have_field_read_listeners_(false), have_field_write_listeners_(false),
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -070072 have_exception_caught_listeners_(false),
73 deoptimized_methods_lock_("deoptimized methods lock"),
74 deoptimization_enabled_(false),
75 interpreter_handler_table_(kMainHandlerTable),
76 quick_alloc_entry_points_instrumentation_counter_(0) {
77}
78
Sebastien Hertza10aa372015-01-21 17:30:58 +010079void Instrumentation::InstallStubsForClass(mirror::Class* klass) {
Sebastien Hertza8a697f2015-01-15 12:28:47 +010080 if (klass->IsErroneous()) {
81 // We can't execute code in a erroneous class: do nothing.
82 } else if (!klass->IsResolved()) {
83 // We need the class to be resolved to install/uninstall stubs. Otherwise its methods
84 // could not be initialized or linked with regards to class inheritance.
85 } else {
86 for (size_t i = 0, e = klass->NumDirectMethods(); i < e; i++) {
87 InstallStubsForMethod(klass->GetDirectMethod(i));
88 }
89 for (size_t i = 0, e = klass->NumVirtualMethods(); i < e; i++) {
90 InstallStubsForMethod(klass->GetVirtualMethod(i));
91 }
jeffhao725a9572012-11-13 18:20:12 -080092 }
jeffhao725a9572012-11-13 18:20:12 -080093}
94
Elliott Hughes956af0f2014-12-11 14:34:28 -080095static void UpdateEntrypoints(mirror::ArtMethod* method, const void* quick_code)
Ian Rogersef7d42f2014-01-06 12:55:46 -080096 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080097 Runtime* const runtime = Runtime::Current();
98 jit::Jit* jit = runtime->GetJit();
99 if (jit != nullptr) {
100 const void* old_code_ptr = method->GetEntryPointFromQuickCompiledCode();
101 jit::JitCodeCache* code_cache = jit->GetCodeCache();
102 if (code_cache->ContainsCodePtr(old_code_ptr)) {
103 // Save the old compiled code since we need it to implement ClassLinker::GetQuickOatCodeFor.
104 code_cache->SaveCompiledCode(method, old_code_ptr);
105 }
106 }
Ian Rogersef7d42f2014-01-06 12:55:46 -0800107 method->SetEntryPointFromQuickCompiledCode(quick_code);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100108 if (!method->IsResolutionMethod()) {
Mingyao Yang98d1cc82014-05-15 17:02:16 -0700109 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700110 if (class_linker->IsQuickToInterpreterBridge(quick_code) ||
111 (class_linker->IsQuickResolutionStub(quick_code) &&
112 Runtime::Current()->GetInstrumentation()->IsForcedInterpretOnly() &&
113 !method->IsNative() && !method->IsProxyMethod())) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800114 DCHECK(!method->IsNative()) << PrettyMethod(method);
Hiroshi Yamauchi563b47c2014-02-28 17:18:37 -0800115 DCHECK(!method->IsProxyMethod()) << PrettyMethod(method);
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700116 method->SetEntryPointFromInterpreter(art::artInterpreterToInterpreterBridge);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100117 } else {
118 method->SetEntryPointFromInterpreter(art::artInterpreterToCompiledCodeBridge);
119 }
120 }
121}
122
123void Instrumentation::InstallStubsForMethod(mirror::ArtMethod* method) {
124 if (method->IsAbstract() || method->IsProxyMethod()) {
125 // Do not change stubs for these methods.
126 return;
127 }
Jeff Hao56802772014-08-19 10:17:36 -0700128 // Don't stub Proxy.<init>. Note that the Proxy class itself is not a proxy class.
129 if (method->IsConstructor() &&
130 method->GetDeclaringClass()->DescriptorEquals("Ljava/lang/reflect/Proxy;")) {
Jeff Haodb8a6642014-08-14 17:18:52 -0700131 return;
132 }
Ian Rogersef7d42f2014-01-06 12:55:46 -0800133 const void* new_quick_code;
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100134 bool uninstall = !entry_exit_stubs_installed_ && !interpreter_stubs_installed_;
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800135 Runtime* const runtime = Runtime::Current();
136 ClassLinker* const class_linker = runtime->GetClassLinker();
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100137 bool is_class_initialized = method->GetDeclaringClass()->IsInitialized();
138 if (uninstall) {
139 if ((forced_interpret_only_ || IsDeoptimized(method)) && !method->IsNative()) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800140 new_quick_code = GetQuickToInterpreterBridge();
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100141 } else if (is_class_initialized || !method->IsStatic() || method->IsConstructor()) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800142 new_quick_code = class_linker->GetQuickOatCodeFor(method);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100143 } else {
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700144 new_quick_code = GetQuickResolutionStub();
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100145 }
146 } else { // !uninstall
Sebastien Hertzbae182c2013-12-17 10:42:03 +0100147 if ((interpreter_stubs_installed_ || forced_interpret_only_ || IsDeoptimized(method)) &&
148 !method->IsNative()) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800149 new_quick_code = GetQuickToInterpreterBridge();
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100150 } else {
151 // Do not overwrite resolution trampoline. When the trampoline initializes the method's
152 // class, all its static methods code will be set to the instrumentation entry point.
153 // For more details, see ClassLinker::FixupStaticTrampolines.
154 if (is_class_initialized || !method->IsStatic() || method->IsConstructor()) {
Sebastien Hertz320deb22014-06-11 19:45:05 +0200155 if (entry_exit_stubs_installed_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800156 new_quick_code = GetQuickInstrumentationEntryPoint();
Sebastien Hertz320deb22014-06-11 19:45:05 +0200157 } else {
Sebastien Hertz320deb22014-06-11 19:45:05 +0200158 new_quick_code = class_linker->GetQuickOatCodeFor(method);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100159 }
160 } else {
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700161 new_quick_code = GetQuickResolutionStub();
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100162 }
163 }
164 }
Elliott Hughes956af0f2014-12-11 14:34:28 -0800165 UpdateEntrypoints(method, new_quick_code);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100166}
167
Ian Rogers62d6c772013-02-27 08:32:07 -0800168// Places the instrumentation exit pc as the return PC for every quick frame. This also allows
169// deoptimization of quick frames to interpreter frames.
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100170// Since we may already have done this previously, we need to push new instrumentation frame before
171// existing instrumentation frames.
Ian Rogers62d6c772013-02-27 08:32:07 -0800172static void InstrumentationInstallStack(Thread* thread, void* arg)
Ian Rogers306057f2012-11-26 12:45:53 -0800173 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
174 struct InstallStackVisitor : public StackVisitor {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800175 InstallStackVisitor(Thread* thread_in, Context* context, uintptr_t instrumentation_exit_pc)
176 : StackVisitor(thread_in, context),
177 instrumentation_stack_(thread_in->GetInstrumentationStack()),
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100178 instrumentation_exit_pc_(instrumentation_exit_pc),
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100179 reached_existing_instrumentation_frames_(false), instrumentation_stack_depth_(0),
180 last_return_pc_(0) {
181 }
jeffhao725a9572012-11-13 18:20:12 -0800182
Ian Rogers306057f2012-11-26 12:45:53 -0800183 virtual bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstromea46f952013-07-30 01:26:50 -0700184 mirror::ArtMethod* m = GetMethod();
Ian Rogers306057f2012-11-26 12:45:53 -0800185 if (m == NULL) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800186 if (kVerboseInstrumentation) {
187 LOG(INFO) << " Skipping upcall. Frame " << GetFrameId();
188 }
189 last_return_pc_ = 0;
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700190 return true; // Ignore upcalls.
Ian Rogers306057f2012-11-26 12:45:53 -0800191 }
Jeff Haoa15a81b2014-05-27 18:25:47 -0700192 if (GetCurrentQuickFrame() == NULL) {
Elliott Hughes956af0f2014-12-11 14:34:28 -0800193 bool interpreter_frame = true;
Sebastien Hertz320deb22014-06-11 19:45:05 +0200194 InstrumentationStackFrame instrumentation_frame(GetThisObject(), m, 0, GetFrameId(),
195 interpreter_frame);
Jeff Haoa15a81b2014-05-27 18:25:47 -0700196 if (kVerboseInstrumentation) {
197 LOG(INFO) << "Pushing shadow frame " << instrumentation_frame.Dump();
198 }
199 shadow_stack_.push_back(instrumentation_frame);
200 return true; // Continue.
201 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800202 uintptr_t return_pc = GetReturnPc();
Sebastien Hertz320deb22014-06-11 19:45:05 +0200203 if (m->IsRuntimeMethod()) {
204 if (return_pc == instrumentation_exit_pc_) {
205 if (kVerboseInstrumentation) {
206 LOG(INFO) << " Handling quick to interpreter transition. Frame " << GetFrameId();
207 }
208 CHECK_LT(instrumentation_stack_depth_, instrumentation_stack_->size());
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200209 const InstrumentationStackFrame& frame =
210 instrumentation_stack_->at(instrumentation_stack_depth_);
Sebastien Hertz320deb22014-06-11 19:45:05 +0200211 CHECK(frame.interpreter_entry_);
212 // This is an interpreter frame so method enter event must have been reported. However we
213 // need to push a DEX pc into the dex_pcs_ list to match size of instrumentation stack.
214 // Since we won't report method entry here, we can safely push any DEX pc.
215 dex_pcs_.push_back(0);
216 last_return_pc_ = frame.return_pc_;
217 ++instrumentation_stack_depth_;
218 return true;
219 } else {
220 if (kVerboseInstrumentation) {
221 LOG(INFO) << " Skipping runtime method. Frame " << GetFrameId();
222 }
223 last_return_pc_ = GetReturnPc();
224 return true; // Ignore unresolved methods since they will be instrumented after resolution.
225 }
226 }
227 if (kVerboseInstrumentation) {
228 LOG(INFO) << " Installing exit stub in " << DescribeLocation();
229 }
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100230 if (return_pc == instrumentation_exit_pc_) {
231 // We've reached a frame which has already been installed with instrumentation exit stub.
232 // We should have already installed instrumentation on previous frames.
233 reached_existing_instrumentation_frames_ = true;
234
235 CHECK_LT(instrumentation_stack_depth_, instrumentation_stack_->size());
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200236 const InstrumentationStackFrame& frame =
237 instrumentation_stack_->at(instrumentation_stack_depth_);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100238 CHECK_EQ(m, frame.method_) << "Expected " << PrettyMethod(m)
239 << ", Found " << PrettyMethod(frame.method_);
240 return_pc = frame.return_pc_;
241 if (kVerboseInstrumentation) {
242 LOG(INFO) << "Ignoring already instrumented " << frame.Dump();
243 }
244 } else {
245 CHECK_NE(return_pc, 0U);
246 CHECK(!reached_existing_instrumentation_frames_);
247 InstrumentationStackFrame instrumentation_frame(GetThisObject(), m, return_pc, GetFrameId(),
248 false);
249 if (kVerboseInstrumentation) {
250 LOG(INFO) << "Pushing frame " << instrumentation_frame.Dump();
251 }
252
Sebastien Hertz320deb22014-06-11 19:45:05 +0200253 // Insert frame at the right position so we do not corrupt the instrumentation stack.
254 // Instrumentation stack frames are in descending frame id order.
255 auto it = instrumentation_stack_->begin();
256 for (auto end = instrumentation_stack_->end(); it != end; ++it) {
257 const InstrumentationStackFrame& current = *it;
258 if (instrumentation_frame.frame_id_ >= current.frame_id_) {
259 break;
260 }
261 }
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100262 instrumentation_stack_->insert(it, instrumentation_frame);
263 SetReturnPc(instrumentation_exit_pc_);
Ian Rogers62d6c772013-02-27 08:32:07 -0800264 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800265 dex_pcs_.push_back(m->ToDexPc(last_return_pc_));
Ian Rogers62d6c772013-02-27 08:32:07 -0800266 last_return_pc_ = return_pc;
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100267 ++instrumentation_stack_depth_;
Ian Rogers306057f2012-11-26 12:45:53 -0800268 return true; // Continue.
269 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800270 std::deque<InstrumentationStackFrame>* const instrumentation_stack_;
Jeff Haoa15a81b2014-05-27 18:25:47 -0700271 std::vector<InstrumentationStackFrame> shadow_stack_;
Ian Rogers62d6c772013-02-27 08:32:07 -0800272 std::vector<uint32_t> dex_pcs_;
Ian Rogers306057f2012-11-26 12:45:53 -0800273 const uintptr_t instrumentation_exit_pc_;
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100274 bool reached_existing_instrumentation_frames_;
275 size_t instrumentation_stack_depth_;
Ian Rogers62d6c772013-02-27 08:32:07 -0800276 uintptr_t last_return_pc_;
Ian Rogers306057f2012-11-26 12:45:53 -0800277 };
Ian Rogers62d6c772013-02-27 08:32:07 -0800278 if (kVerboseInstrumentation) {
279 std::string thread_name;
280 thread->GetThreadName(thread_name);
281 LOG(INFO) << "Installing exit stubs in " << thread_name;
Ian Rogers306057f2012-11-26 12:45:53 -0800282 }
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100283
284 Instrumentation* instrumentation = reinterpret_cast<Instrumentation*>(arg);
Ian Rogers700a4022014-05-19 16:49:03 -0700285 std::unique_ptr<Context> context(Context::Create());
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700286 uintptr_t instrumentation_exit_pc = reinterpret_cast<uintptr_t>(GetQuickInstrumentationExitPc());
Sebastien Hertz11d40c22014-02-19 18:00:17 +0100287 InstallStackVisitor visitor(thread, context.get(), instrumentation_exit_pc);
Ian Rogers62d6c772013-02-27 08:32:07 -0800288 visitor.WalkStack(true);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100289 CHECK_EQ(visitor.dex_pcs_.size(), thread->GetInstrumentationStack()->size());
Ian Rogers62d6c772013-02-27 08:32:07 -0800290
Sebastien Hertz7ec2f1c2014-03-27 20:06:47 +0100291 if (instrumentation->ShouldNotifyMethodEnterExitEvents()) {
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100292 // Create method enter events for all methods currently on the thread's stack. We only do this
293 // if no debugger is attached to prevent from posting events twice.
Jeff Haoa15a81b2014-05-27 18:25:47 -0700294 auto ssi = visitor.shadow_stack_.rbegin();
295 for (auto isi = thread->GetInstrumentationStack()->rbegin(),
296 end = thread->GetInstrumentationStack()->rend(); isi != end; ++isi) {
297 while (ssi != visitor.shadow_stack_.rend() && (*ssi).frame_id_ < (*isi).frame_id_) {
298 instrumentation->MethodEnterEvent(thread, (*ssi).this_object_, (*ssi).method_, 0);
299 ++ssi;
300 }
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100301 uint32_t dex_pc = visitor.dex_pcs_.back();
302 visitor.dex_pcs_.pop_back();
Sebastien Hertz320deb22014-06-11 19:45:05 +0200303 if (!isi->interpreter_entry_) {
304 instrumentation->MethodEnterEvent(thread, (*isi).this_object_, (*isi).method_, dex_pc);
305 }
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100306 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800307 }
308 thread->VerifyStack();
Ian Rogers306057f2012-11-26 12:45:53 -0800309}
310
Ian Rogers62d6c772013-02-27 08:32:07 -0800311// Removes the instrumentation exit pc as the return PC for every quick frame.
312static void InstrumentationRestoreStack(Thread* thread, void* arg)
Ian Rogers306057f2012-11-26 12:45:53 -0800313 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
314 struct RestoreStackVisitor : public StackVisitor {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800315 RestoreStackVisitor(Thread* thread_in, uintptr_t instrumentation_exit_pc,
Ian Rogers62d6c772013-02-27 08:32:07 -0800316 Instrumentation* instrumentation)
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800317 : StackVisitor(thread_in, NULL), thread_(thread_in),
Ian Rogers62d6c772013-02-27 08:32:07 -0800318 instrumentation_exit_pc_(instrumentation_exit_pc),
319 instrumentation_(instrumentation),
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800320 instrumentation_stack_(thread_in->GetInstrumentationStack()),
Ian Rogers62d6c772013-02-27 08:32:07 -0800321 frames_removed_(0) {}
Ian Rogers306057f2012-11-26 12:45:53 -0800322
323 virtual bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800324 if (instrumentation_stack_->size() == 0) {
jeffhao725a9572012-11-13 18:20:12 -0800325 return false; // Stop.
326 }
Brian Carlstromea46f952013-07-30 01:26:50 -0700327 mirror::ArtMethod* m = GetMethod();
Ian Rogers62d6c772013-02-27 08:32:07 -0800328 if (GetCurrentQuickFrame() == NULL) {
329 if (kVerboseInstrumentation) {
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200330 LOG(INFO) << " Ignoring a shadow frame. Frame " << GetFrameId()
331 << " Method=" << PrettyMethod(m);
Ian Rogers62d6c772013-02-27 08:32:07 -0800332 }
333 return true; // Ignore shadow frames.
334 }
Ian Rogers306057f2012-11-26 12:45:53 -0800335 if (m == NULL) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800336 if (kVerboseInstrumentation) {
337 LOG(INFO) << " Skipping upcall. Frame " << GetFrameId();
338 }
Ian Rogers306057f2012-11-26 12:45:53 -0800339 return true; // Ignore upcalls.
340 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800341 bool removed_stub = false;
342 // TODO: make this search more efficient?
Sebastien Hertz7ec2f1c2014-03-27 20:06:47 +0100343 const size_t frameId = GetFrameId();
344 for (const InstrumentationStackFrame& instrumentation_frame : *instrumentation_stack_) {
345 if (instrumentation_frame.frame_id_ == frameId) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800346 if (kVerboseInstrumentation) {
347 LOG(INFO) << " Removing exit stub in " << DescribeLocation();
348 }
Jeff Hao9a916d32013-06-27 18:45:37 -0700349 if (instrumentation_frame.interpreter_entry_) {
350 CHECK(m == Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs));
351 } else {
352 CHECK(m == instrumentation_frame.method_) << PrettyMethod(m);
353 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800354 SetReturnPc(instrumentation_frame.return_pc_);
Sebastien Hertz7ec2f1c2014-03-27 20:06:47 +0100355 if (instrumentation_->ShouldNotifyMethodEnterExitEvents()) {
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100356 // Create the method exit events. As the methods didn't really exit the result is 0.
357 // We only do this if no debugger is attached to prevent from posting events twice.
358 instrumentation_->MethodExitEvent(thread_, instrumentation_frame.this_object_, m,
359 GetDexPc(), JValue());
360 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800361 frames_removed_++;
362 removed_stub = true;
363 break;
364 }
365 }
366 if (!removed_stub) {
367 if (kVerboseInstrumentation) {
368 LOG(INFO) << " No exit stub in " << DescribeLocation();
Ian Rogers306057f2012-11-26 12:45:53 -0800369 }
jeffhao725a9572012-11-13 18:20:12 -0800370 }
371 return true; // Continue.
372 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800373 Thread* const thread_;
Ian Rogers306057f2012-11-26 12:45:53 -0800374 const uintptr_t instrumentation_exit_pc_;
Ian Rogers62d6c772013-02-27 08:32:07 -0800375 Instrumentation* const instrumentation_;
376 std::deque<instrumentation::InstrumentationStackFrame>* const instrumentation_stack_;
377 size_t frames_removed_;
jeffhao725a9572012-11-13 18:20:12 -0800378 };
Ian Rogers62d6c772013-02-27 08:32:07 -0800379 if (kVerboseInstrumentation) {
380 std::string thread_name;
381 thread->GetThreadName(thread_name);
382 LOG(INFO) << "Removing exit stubs in " << thread_name;
383 }
384 std::deque<instrumentation::InstrumentationStackFrame>* stack = thread->GetInstrumentationStack();
385 if (stack->size() > 0) {
386 Instrumentation* instrumentation = reinterpret_cast<Instrumentation*>(arg);
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700387 uintptr_t instrumentation_exit_pc =
388 reinterpret_cast<uintptr_t>(GetQuickInstrumentationExitPc());
Ian Rogers62d6c772013-02-27 08:32:07 -0800389 RestoreStackVisitor visitor(thread, instrumentation_exit_pc, instrumentation);
390 visitor.WalkStack(true);
391 CHECK_EQ(visitor.frames_removed_, stack->size());
392 while (stack->size() > 0) {
393 stack->pop_front();
394 }
jeffhao725a9572012-11-13 18:20:12 -0800395 }
396}
397
Ian Rogers62d6c772013-02-27 08:32:07 -0800398void Instrumentation::AddListener(InstrumentationListener* listener, uint32_t events) {
399 Locks::mutator_lock_->AssertExclusiveHeld(Thread::Current());
Ian Rogers62d6c772013-02-27 08:32:07 -0800400 if ((events & kMethodEntered) != 0) {
401 method_entry_listeners_.push_back(listener);
Ian Rogers62d6c772013-02-27 08:32:07 -0800402 have_method_entry_listeners_ = true;
403 }
404 if ((events & kMethodExited) != 0) {
405 method_exit_listeners_.push_back(listener);
Ian Rogers62d6c772013-02-27 08:32:07 -0800406 have_method_exit_listeners_ = true;
407 }
408 if ((events & kMethodUnwind) != 0) {
409 method_unwind_listeners_.push_back(listener);
410 have_method_unwind_listeners_ = true;
411 }
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800412 if ((events & kBackwardBranch) != 0) {
413 backward_branch_listeners_.push_back(listener);
414 have_backward_branch_listeners_ = true;
415 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800416 if ((events & kDexPcMoved) != 0) {
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200417 std::list<InstrumentationListener*>* modified;
418 if (have_dex_pc_listeners_) {
419 modified = new std::list<InstrumentationListener*>(*dex_pc_listeners_.get());
420 } else {
421 modified = new std::list<InstrumentationListener*>();
422 }
423 modified->push_back(listener);
424 dex_pc_listeners_.reset(modified);
Ian Rogers62d6c772013-02-27 08:32:07 -0800425 have_dex_pc_listeners_ = true;
426 }
Sebastien Hertz3f52eaf2014-04-04 17:50:18 +0200427 if ((events & kFieldRead) != 0) {
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200428 std::list<InstrumentationListener*>* modified;
429 if (have_field_read_listeners_) {
430 modified = new std::list<InstrumentationListener*>(*field_read_listeners_.get());
431 } else {
432 modified = new std::list<InstrumentationListener*>();
433 }
434 modified->push_back(listener);
435 field_read_listeners_.reset(modified);
Sebastien Hertz3f52eaf2014-04-04 17:50:18 +0200436 have_field_read_listeners_ = true;
437 }
438 if ((events & kFieldWritten) != 0) {
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200439 std::list<InstrumentationListener*>* modified;
440 if (have_field_write_listeners_) {
441 modified = new std::list<InstrumentationListener*>(*field_write_listeners_.get());
442 } else {
443 modified = new std::list<InstrumentationListener*>();
444 }
445 modified->push_back(listener);
446 field_write_listeners_.reset(modified);
Sebastien Hertz3f52eaf2014-04-04 17:50:18 +0200447 have_field_write_listeners_ = true;
448 }
Jeff Hao14dd5a82013-04-11 10:23:36 -0700449 if ((events & kExceptionCaught) != 0) {
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200450 std::list<InstrumentationListener*>* modified;
451 if (have_exception_caught_listeners_) {
452 modified = new std::list<InstrumentationListener*>(*exception_caught_listeners_.get());
453 } else {
454 modified = new std::list<InstrumentationListener*>();
455 }
456 modified->push_back(listener);
457 exception_caught_listeners_.reset(modified);
Jeff Hao14dd5a82013-04-11 10:23:36 -0700458 have_exception_caught_listeners_ = true;
459 }
Sebastien Hertzee1997a2013-09-19 14:47:09 +0200460 UpdateInterpreterHandlerTable();
jeffhao725a9572012-11-13 18:20:12 -0800461}
462
Ian Rogers62d6c772013-02-27 08:32:07 -0800463void Instrumentation::RemoveListener(InstrumentationListener* listener, uint32_t events) {
464 Locks::mutator_lock_->AssertExclusiveHeld(Thread::Current());
Ian Rogers62d6c772013-02-27 08:32:07 -0800465
466 if ((events & kMethodEntered) != 0) {
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200467 if (have_method_entry_listeners_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800468 method_entry_listeners_.remove(listener);
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200469 have_method_entry_listeners_ = !method_entry_listeners_.empty();
Ian Rogers62d6c772013-02-27 08:32:07 -0800470 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800471 }
472 if ((events & kMethodExited) != 0) {
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200473 if (have_method_exit_listeners_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800474 method_exit_listeners_.remove(listener);
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200475 have_method_exit_listeners_ = !method_exit_listeners_.empty();
Ian Rogers62d6c772013-02-27 08:32:07 -0800476 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800477 }
478 if ((events & kMethodUnwind) != 0) {
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200479 if (have_method_unwind_listeners_) {
480 method_unwind_listeners_.remove(listener);
481 have_method_unwind_listeners_ = !method_unwind_listeners_.empty();
482 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800483 }
484 if ((events & kDexPcMoved) != 0) {
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200485 if (have_dex_pc_listeners_) {
486 std::list<InstrumentationListener*>* modified =
487 new std::list<InstrumentationListener*>(*dex_pc_listeners_.get());
488 modified->remove(listener);
489 have_dex_pc_listeners_ = !modified->empty();
490 if (have_dex_pc_listeners_) {
491 dex_pc_listeners_.reset(modified);
492 } else {
493 dex_pc_listeners_.reset();
494 delete modified;
495 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800496 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800497 }
Sebastien Hertz3f52eaf2014-04-04 17:50:18 +0200498 if ((events & kFieldRead) != 0) {
Daniel Mihalyi66445212014-08-21 15:57:25 +0200499 if (have_field_read_listeners_) {
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200500 std::list<InstrumentationListener*>* modified =
501 new std::list<InstrumentationListener*>(*field_read_listeners_.get());
502 modified->remove(listener);
503 have_field_read_listeners_ = !modified->empty();
504 if (have_field_read_listeners_) {
505 field_read_listeners_.reset(modified);
506 } else {
507 field_read_listeners_.reset();
508 delete modified;
509 }
Sebastien Hertz3f52eaf2014-04-04 17:50:18 +0200510 }
Sebastien Hertz3f52eaf2014-04-04 17:50:18 +0200511 }
512 if ((events & kFieldWritten) != 0) {
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200513 if (have_field_write_listeners_) {
514 std::list<InstrumentationListener*>* modified =
515 new std::list<InstrumentationListener*>(*field_write_listeners_.get());
516 modified->remove(listener);
517 have_field_write_listeners_ = !modified->empty();
518 if (have_field_write_listeners_) {
519 field_write_listeners_.reset(modified);
520 } else {
521 field_write_listeners_.reset();
522 delete modified;
523 }
Sebastien Hertz3f52eaf2014-04-04 17:50:18 +0200524 }
Sebastien Hertz3f52eaf2014-04-04 17:50:18 +0200525 }
Jeff Hao14dd5a82013-04-11 10:23:36 -0700526 if ((events & kExceptionCaught) != 0) {
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200527 if (have_exception_caught_listeners_) {
528 std::list<InstrumentationListener*>* modified =
529 new std::list<InstrumentationListener*>(*exception_caught_listeners_.get());
530 modified->remove(listener);
531 have_exception_caught_listeners_ = !modified->empty();
532 if (have_exception_caught_listeners_) {
533 exception_caught_listeners_.reset(modified);
534 } else {
535 exception_caught_listeners_.reset();
536 delete modified;
537 }
538 }
Jeff Hao14dd5a82013-04-11 10:23:36 -0700539 }
Sebastien Hertzee1997a2013-09-19 14:47:09 +0200540 UpdateInterpreterHandlerTable();
jeffhao725a9572012-11-13 18:20:12 -0800541}
542
Ian Rogers62d6c772013-02-27 08:32:07 -0800543void Instrumentation::ConfigureStubs(bool require_entry_exit_stubs, bool require_interpreter) {
544 interpret_only_ = require_interpreter || forced_interpret_only_;
545 // Compute what level of instrumentation is required and compare to current.
546 int desired_level, current_level;
547 if (require_interpreter) {
548 desired_level = 2;
549 } else if (require_entry_exit_stubs) {
550 desired_level = 1;
551 } else {
552 desired_level = 0;
553 }
554 if (interpreter_stubs_installed_) {
555 current_level = 2;
556 } else if (entry_exit_stubs_installed_) {
557 current_level = 1;
558 } else {
559 current_level = 0;
560 }
561 if (desired_level == current_level) {
562 // We're already set.
563 return;
564 }
Sebastien Hertz7ec2f1c2014-03-27 20:06:47 +0100565 Thread* const self = Thread::Current();
Ian Rogers62d6c772013-02-27 08:32:07 -0800566 Runtime* runtime = Runtime::Current();
Sebastien Hertza8a697f2015-01-15 12:28:47 +0100567 Locks::mutator_lock_->AssertExclusiveHeld(self);
Ian Rogers62d6c772013-02-27 08:32:07 -0800568 Locks::thread_list_lock_->AssertNotHeld(self);
569 if (desired_level > 0) {
570 if (require_interpreter) {
571 interpreter_stubs_installed_ = true;
572 } else {
573 CHECK(require_entry_exit_stubs);
574 entry_exit_stubs_installed_ = true;
575 }
576 runtime->GetClassLinker()->VisitClasses(InstallStubsClassVisitor, this);
577 instrumentation_stubs_installed_ = true;
Sebastien Hertz7ec2f1c2014-03-27 20:06:47 +0100578 MutexLock mu(self, *Locks::thread_list_lock_);
Ian Rogers62d6c772013-02-27 08:32:07 -0800579 runtime->GetThreadList()->ForEach(InstrumentationInstallStack, this);
580 } else {
581 interpreter_stubs_installed_ = false;
582 entry_exit_stubs_installed_ = false;
583 runtime->GetClassLinker()->VisitClasses(InstallStubsClassVisitor, this);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100584 // Restore stack only if there is no method currently deoptimized.
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -0700585 bool empty;
586 {
587 ReaderMutexLock mu(self, deoptimized_methods_lock_);
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700588 empty = IsDeoptimizedMethodsEmpty(); // Avoid lock violation.
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -0700589 }
590 if (empty) {
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100591 instrumentation_stubs_installed_ = false;
592 MutexLock mu(self, *Locks::thread_list_lock_);
593 Runtime::Current()->GetThreadList()->ForEach(InstrumentationRestoreStack, this);
594 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800595 }
jeffhao725a9572012-11-13 18:20:12 -0800596}
597
Ian Rogersfa824272013-11-05 16:12:57 -0800598static void ResetQuickAllocEntryPointsForThread(Thread* thread, void* arg) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700599 UNUSED(arg);
Ian Rogersfa824272013-11-05 16:12:57 -0800600 thread->ResetQuickAllocEntryPointsForThread();
601}
602
Mathieu Chartier9ef78b52014-09-25 17:03:12 -0700603void Instrumentation::SetEntrypointsInstrumented(bool instrumented) {
604 Thread* self = Thread::Current();
Mathieu Chartier661974a2014-01-09 11:23:53 -0800605 Runtime* runtime = Runtime::Current();
606 ThreadList* tl = runtime->GetThreadList();
Mathieu Chartier9ef78b52014-09-25 17:03:12 -0700607 Locks::mutator_lock_->AssertNotHeld(self);
608 Locks::instrument_entrypoints_lock_->AssertHeld(self);
609 if (runtime->IsStarted()) {
Mathieu Chartier661974a2014-01-09 11:23:53 -0800610 tl->SuspendAll();
611 }
612 {
Mathieu Chartier9ef78b52014-09-25 17:03:12 -0700613 MutexLock mu(self, *Locks::runtime_shutdown_lock_);
Mathieu Chartier661974a2014-01-09 11:23:53 -0800614 SetQuickAllocEntryPointsInstrumented(instrumented);
615 ResetQuickAllocEntryPoints();
616 }
Mathieu Chartier9ef78b52014-09-25 17:03:12 -0700617 if (runtime->IsStarted()) {
Mathieu Chartier661974a2014-01-09 11:23:53 -0800618 tl->ResumeAll();
619 }
620}
621
Mathieu Chartier9ef78b52014-09-25 17:03:12 -0700622void Instrumentation::InstrumentQuickAllocEntryPoints() {
623 MutexLock mu(Thread::Current(), *Locks::instrument_entrypoints_lock_);
624 InstrumentQuickAllocEntryPointsLocked();
Ian Rogersfa824272013-11-05 16:12:57 -0800625}
626
Mathieu Chartier9ef78b52014-09-25 17:03:12 -0700627void Instrumentation::UninstrumentQuickAllocEntryPoints() {
628 MutexLock mu(Thread::Current(), *Locks::instrument_entrypoints_lock_);
629 UninstrumentQuickAllocEntryPointsLocked();
630}
631
632void Instrumentation::InstrumentQuickAllocEntryPointsLocked() {
633 Locks::instrument_entrypoints_lock_->AssertHeld(Thread::Current());
634 if (quick_alloc_entry_points_instrumentation_counter_ == 0) {
635 SetEntrypointsInstrumented(true);
Mathieu Chartiercbb2d202013-11-14 17:45:16 -0800636 }
Mathieu Chartier9ef78b52014-09-25 17:03:12 -0700637 ++quick_alloc_entry_points_instrumentation_counter_;
Mathieu Chartier9ef78b52014-09-25 17:03:12 -0700638}
639
640void Instrumentation::UninstrumentQuickAllocEntryPointsLocked() {
641 Locks::instrument_entrypoints_lock_->AssertHeld(Thread::Current());
642 CHECK_GT(quick_alloc_entry_points_instrumentation_counter_, 0U);
643 --quick_alloc_entry_points_instrumentation_counter_;
644 if (quick_alloc_entry_points_instrumentation_counter_ == 0) {
645 SetEntrypointsInstrumented(false);
646 }
Mathieu Chartiercbb2d202013-11-14 17:45:16 -0800647}
648
649void Instrumentation::ResetQuickAllocEntryPoints() {
650 Runtime* runtime = Runtime::Current();
651 if (runtime->IsStarted()) {
Mathieu Chartiere6da9af2013-12-16 11:54:42 -0800652 MutexLock mu(Thread::Current(), *Locks::thread_list_lock_);
653 runtime->GetThreadList()->ForEach(ResetQuickAllocEntryPointsForThread, NULL);
Ian Rogersfa824272013-11-05 16:12:57 -0800654 }
655}
656
Elliott Hughes956af0f2014-12-11 14:34:28 -0800657void Instrumentation::UpdateMethodsCode(mirror::ArtMethod* method, const void* quick_code) {
Sebastien Hertza8a697f2015-01-15 12:28:47 +0100658 DCHECK(method->GetDeclaringClass()->IsResolved());
Ian Rogersef7d42f2014-01-06 12:55:46 -0800659 const void* new_quick_code;
Ian Rogers62d6c772013-02-27 08:32:07 -0800660 if (LIKELY(!instrumentation_stubs_installed_)) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800661 new_quick_code = quick_code;
Jeff Hao65d15d92013-07-16 16:39:33 -0700662 } else {
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100663 if ((interpreter_stubs_installed_ || IsDeoptimized(method)) && !method->IsNative()) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800664 new_quick_code = GetQuickToInterpreterBridge();
Jeff Hao65d15d92013-07-16 16:39:33 -0700665 } else {
Mingyao Yang98d1cc82014-05-15 17:02:16 -0700666 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700667 if (class_linker->IsQuickResolutionStub(quick_code) ||
668 class_linker->IsQuickToInterpreterBridge(quick_code)) {
Mingyao Yang98d1cc82014-05-15 17:02:16 -0700669 new_quick_code = quick_code;
Mingyao Yang98d1cc82014-05-15 17:02:16 -0700670 } else if (entry_exit_stubs_installed_) {
671 new_quick_code = GetQuickInstrumentationEntryPoint();
Mingyao Yang98d1cc82014-05-15 17:02:16 -0700672 } else {
Mingyao Yang98d1cc82014-05-15 17:02:16 -0700673 new_quick_code = quick_code;
Mingyao Yang98d1cc82014-05-15 17:02:16 -0700674 }
Jeff Hao65d15d92013-07-16 16:39:33 -0700675 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800676 }
Elliott Hughes956af0f2014-12-11 14:34:28 -0800677 UpdateEntrypoints(method, new_quick_code);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100678}
679
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700680bool Instrumentation::AddDeoptimizedMethod(mirror::ArtMethod* method) {
681 // Note that the insert() below isn't read barrier-aware. So, this
682 // FindDeoptimizedMethod() call is necessary or else we would end up
683 // storing the same method twice in the map (the from-space and the
684 // to-space ones).
685 if (FindDeoptimizedMethod(method)) {
686 // Already in the map. Return.
687 return false;
688 }
689 // Not found. Add it.
Mathieu Chartier4c4d6092015-01-22 17:02:27 -0800690 static_assert(!kMovingMethods, "Not safe if methods can move");
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700691 int32_t hash_code = method->IdentityHashCode();
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700692 deoptimized_methods_.insert(std::make_pair(hash_code, GcRoot<mirror::ArtMethod>(method)));
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700693 return true;
694}
695
696bool Instrumentation::FindDeoptimizedMethod(mirror::ArtMethod* method) {
Mathieu Chartier4c4d6092015-01-22 17:02:27 -0800697 static_assert(!kMovingMethods, "Not safe if methods can move");
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700698 int32_t hash_code = method->IdentityHashCode();
699 auto range = deoptimized_methods_.equal_range(hash_code);
700 for (auto it = range.first; it != range.second; ++it) {
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700701 mirror::ArtMethod* m = it->second.Read();
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700702 if (m == method) {
703 // Found.
704 return true;
705 }
706 }
707 // Not found.
708 return false;
709}
710
711mirror::ArtMethod* Instrumentation::BeginDeoptimizedMethod() {
712 auto it = deoptimized_methods_.begin();
713 if (it == deoptimized_methods_.end()) {
714 // Empty.
715 return nullptr;
716 }
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700717 return it->second.Read();
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700718}
719
720bool Instrumentation::RemoveDeoptimizedMethod(mirror::ArtMethod* method) {
Mathieu Chartier4c4d6092015-01-22 17:02:27 -0800721 static_assert(!kMovingMethods, "Not safe if methods can move");
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700722 int32_t hash_code = method->IdentityHashCode();
723 auto range = deoptimized_methods_.equal_range(hash_code);
724 for (auto it = range.first; it != range.second; ++it) {
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700725 mirror::ArtMethod* m = it->second.Read();
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700726 if (m == method) {
727 // Found. Erase and return.
728 deoptimized_methods_.erase(it);
729 return true;
730 }
731 }
732 // Not found.
733 return false;
734}
735
736bool Instrumentation::IsDeoptimizedMethodsEmpty() const {
737 return deoptimized_methods_.empty();
738}
739
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100740void Instrumentation::Deoptimize(mirror::ArtMethod* method) {
741 CHECK(!method->IsNative());
742 CHECK(!method->IsProxyMethod());
743 CHECK(!method->IsAbstract());
744
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -0700745 Thread* self = Thread::Current();
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -0700746 {
747 WriterMutexLock mu(self, deoptimized_methods_lock_);
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700748 bool has_not_been_deoptimized = AddDeoptimizedMethod(method);
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200749 CHECK(has_not_been_deoptimized) << "Method " << PrettyMethod(method)
750 << " is already deoptimized";
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -0700751 }
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100752 if (!interpreter_stubs_installed_) {
Elliott Hughes956af0f2014-12-11 14:34:28 -0800753 UpdateEntrypoints(method, GetQuickInstrumentationEntryPoint());
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100754
755 // Install instrumentation exit stub and instrumentation frames. We may already have installed
756 // these previously so it will only cover the newly created frames.
757 instrumentation_stubs_installed_ = true;
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -0700758 MutexLock mu(self, *Locks::thread_list_lock_);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100759 Runtime::Current()->GetThreadList()->ForEach(InstrumentationInstallStack, this);
760 }
761}
762
763void Instrumentation::Undeoptimize(mirror::ArtMethod* method) {
764 CHECK(!method->IsNative());
765 CHECK(!method->IsProxyMethod());
766 CHECK(!method->IsAbstract());
767
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -0700768 Thread* self = Thread::Current();
769 bool empty;
770 {
771 WriterMutexLock mu(self, deoptimized_methods_lock_);
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700772 bool found_and_erased = RemoveDeoptimizedMethod(method);
773 CHECK(found_and_erased) << "Method " << PrettyMethod(method)
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -0700774 << " is not deoptimized";
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700775 empty = IsDeoptimizedMethodsEmpty();
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -0700776 }
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100777
778 // Restore code and possibly stack only if we did not deoptimize everything.
779 if (!interpreter_stubs_installed_) {
780 // Restore its code or resolution trampoline.
781 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Ian Rogersef7d42f2014-01-06 12:55:46 -0800782 if (method->IsStatic() && !method->IsConstructor() &&
783 !method->GetDeclaringClass()->IsInitialized()) {
Elliott Hughes956af0f2014-12-11 14:34:28 -0800784 UpdateEntrypoints(method, GetQuickResolutionStub());
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100785 } else {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800786 const void* quick_code = class_linker->GetQuickOatCodeFor(method);
Elliott Hughes956af0f2014-12-11 14:34:28 -0800787 UpdateEntrypoints(method, quick_code);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100788 }
789
790 // If there is no deoptimized method left, we can restore the stack of each thread.
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -0700791 if (empty) {
792 MutexLock mu(self, *Locks::thread_list_lock_);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100793 Runtime::Current()->GetThreadList()->ForEach(InstrumentationRestoreStack, this);
794 instrumentation_stubs_installed_ = false;
795 }
796 }
797}
798
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700799bool Instrumentation::IsDeoptimized(mirror::ArtMethod* method) {
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100800 DCHECK(method != nullptr);
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700801 ReaderMutexLock mu(Thread::Current(), deoptimized_methods_lock_);
802 return FindDeoptimizedMethod(method);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100803}
804
805void Instrumentation::EnableDeoptimization() {
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -0700806 ReaderMutexLock mu(Thread::Current(), deoptimized_methods_lock_);
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700807 CHECK(IsDeoptimizedMethodsEmpty());
Sebastien Hertz11d40c22014-02-19 18:00:17 +0100808 CHECK_EQ(deoptimization_enabled_, false);
809 deoptimization_enabled_ = true;
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100810}
811
812void Instrumentation::DisableDeoptimization() {
Sebastien Hertz11d40c22014-02-19 18:00:17 +0100813 CHECK_EQ(deoptimization_enabled_, true);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100814 // If we deoptimized everything, undo it.
815 if (interpreter_stubs_installed_) {
816 UndeoptimizeEverything();
817 }
818 // Undeoptimized selected methods.
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -0700819 while (true) {
820 mirror::ArtMethod* method;
821 {
822 ReaderMutexLock mu(Thread::Current(), deoptimized_methods_lock_);
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700823 if (IsDeoptimizedMethodsEmpty()) {
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -0700824 break;
825 }
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700826 method = BeginDeoptimizedMethod();
827 CHECK(method != nullptr);
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -0700828 }
829 Undeoptimize(method);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100830 }
Sebastien Hertz11d40c22014-02-19 18:00:17 +0100831 deoptimization_enabled_ = false;
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100832}
833
Sebastien Hertz11d40c22014-02-19 18:00:17 +0100834// Indicates if instrumentation should notify method enter/exit events to the listeners.
835bool Instrumentation::ShouldNotifyMethodEnterExitEvents() const {
Sebastien Hertz7ec2f1c2014-03-27 20:06:47 +0100836 return !deoptimization_enabled_ && !interpreter_stubs_installed_;
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100837}
838
839void Instrumentation::DeoptimizeEverything() {
840 CHECK(!interpreter_stubs_installed_);
841 ConfigureStubs(false, true);
842}
843
844void Instrumentation::UndeoptimizeEverything() {
845 CHECK(interpreter_stubs_installed_);
846 ConfigureStubs(false, false);
847}
848
849void Instrumentation::EnableMethodTracing() {
850 bool require_interpreter = kDeoptimizeForAccurateMethodEntryExitListeners;
851 ConfigureStubs(!require_interpreter, require_interpreter);
852}
853
854void Instrumentation::DisableMethodTracing() {
855 ConfigureStubs(false, false);
jeffhao725a9572012-11-13 18:20:12 -0800856}
857
Mathieu Chartiera7dd0382014-11-20 17:08:58 -0800858const void* Instrumentation::GetQuickCodeFor(mirror::ArtMethod* method, size_t pointer_size) const {
Ian Rogers62d6c772013-02-27 08:32:07 -0800859 Runtime* runtime = Runtime::Current();
860 if (LIKELY(!instrumentation_stubs_installed_)) {
Mathieu Chartiera7dd0382014-11-20 17:08:58 -0800861 const void* code = method->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
Vladimir Marko8a630572014-04-09 18:45:35 +0100862 DCHECK(code != nullptr);
Mingyao Yang98d1cc82014-05-15 17:02:16 -0700863 ClassLinker* class_linker = runtime->GetClassLinker();
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700864 if (LIKELY(!class_linker->IsQuickResolutionStub(code) &&
865 !class_linker->IsQuickToInterpreterBridge(code)) &&
866 !class_linker->IsQuickResolutionStub(code) &&
867 !class_linker->IsQuickToInterpreterBridge(code)) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800868 return code;
869 }
870 }
Ian Rogersef7d42f2014-01-06 12:55:46 -0800871 return runtime->GetClassLinker()->GetQuickOatCodeFor(method);
jeffhao725a9572012-11-13 18:20:12 -0800872}
873
Ian Rogers62d6c772013-02-27 08:32:07 -0800874void Instrumentation::MethodEnterEventImpl(Thread* thread, mirror::Object* this_object,
Ian Rogersef7d42f2014-01-06 12:55:46 -0800875 mirror::ArtMethod* method,
Ian Rogers62d6c772013-02-27 08:32:07 -0800876 uint32_t dex_pc) const {
Mathieu Chartier02e25112013-08-14 16:14:24 -0700877 auto it = method_entry_listeners_.begin();
Jeff Hao65d15d92013-07-16 16:39:33 -0700878 bool is_end = (it == method_entry_listeners_.end());
879 // Implemented this way to prevent problems caused by modification of the list while iterating.
880 while (!is_end) {
881 InstrumentationListener* cur = *it;
882 ++it;
883 is_end = (it == method_entry_listeners_.end());
884 cur->MethodEntered(thread, this_object, method, dex_pc);
Ian Rogers62d6c772013-02-27 08:32:07 -0800885 }
886}
887
888void Instrumentation::MethodExitEventImpl(Thread* thread, mirror::Object* this_object,
Ian Rogersef7d42f2014-01-06 12:55:46 -0800889 mirror::ArtMethod* method,
Ian Rogers62d6c772013-02-27 08:32:07 -0800890 uint32_t dex_pc, const JValue& return_value) const {
Mathieu Chartier02e25112013-08-14 16:14:24 -0700891 auto it = method_exit_listeners_.begin();
Jeff Hao65d15d92013-07-16 16:39:33 -0700892 bool is_end = (it == method_exit_listeners_.end());
893 // Implemented this way to prevent problems caused by modification of the list while iterating.
894 while (!is_end) {
895 InstrumentationListener* cur = *it;
896 ++it;
897 is_end = (it == method_exit_listeners_.end());
898 cur->MethodExited(thread, this_object, method, dex_pc, return_value);
Ian Rogers62d6c772013-02-27 08:32:07 -0800899 }
900}
901
902void Instrumentation::MethodUnwindEvent(Thread* thread, mirror::Object* this_object,
Ian Rogersef7d42f2014-01-06 12:55:46 -0800903 mirror::ArtMethod* method,
Ian Rogers62d6c772013-02-27 08:32:07 -0800904 uint32_t dex_pc) const {
905 if (have_method_unwind_listeners_) {
Mathieu Chartier02e25112013-08-14 16:14:24 -0700906 for (InstrumentationListener* listener : method_unwind_listeners_) {
Sebastien Hertz51db44a2013-11-19 10:00:29 +0100907 listener->MethodUnwind(thread, this_object, method, dex_pc);
Ian Rogers62d6c772013-02-27 08:32:07 -0800908 }
909 }
910}
911
912void Instrumentation::DexPcMovedEventImpl(Thread* thread, mirror::Object* this_object,
Ian Rogersef7d42f2014-01-06 12:55:46 -0800913 mirror::ArtMethod* method,
Ian Rogers62d6c772013-02-27 08:32:07 -0800914 uint32_t dex_pc) const {
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200915 if (HasDexPcListeners()) {
916 std::shared_ptr<std::list<InstrumentationListener*>> original(dex_pc_listeners_);
917 for (InstrumentationListener* listener : *original.get()) {
918 listener->DexPcMoved(thread, this_object, method, dex_pc);
919 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800920 }
921}
922
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800923void Instrumentation::BackwardBranchImpl(Thread* thread, mirror::ArtMethod* method,
924 int32_t offset) const {
925 for (InstrumentationListener* listener : backward_branch_listeners_) {
926 listener->BackwardBranch(thread, method, offset);
927 }
928}
929
Sebastien Hertz3f52eaf2014-04-04 17:50:18 +0200930void Instrumentation::FieldReadEventImpl(Thread* thread, mirror::Object* this_object,
931 mirror::ArtMethod* method, uint32_t dex_pc,
932 mirror::ArtField* field) const {
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200933 if (HasFieldReadListeners()) {
934 std::shared_ptr<std::list<InstrumentationListener*>> original(field_read_listeners_);
935 for (InstrumentationListener* listener : *original.get()) {
936 listener->FieldRead(thread, this_object, method, dex_pc, field);
937 }
Sebastien Hertz3f52eaf2014-04-04 17:50:18 +0200938 }
939}
940
941void Instrumentation::FieldWriteEventImpl(Thread* thread, mirror::Object* this_object,
942 mirror::ArtMethod* method, uint32_t dex_pc,
943 mirror::ArtField* field, const JValue& field_value) const {
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200944 if (HasFieldWriteListeners()) {
945 std::shared_ptr<std::list<InstrumentationListener*>> original(field_write_listeners_);
946 for (InstrumentationListener* listener : *original.get()) {
947 listener->FieldWritten(thread, this_object, method, dex_pc, field, field_value);
948 }
Sebastien Hertz3f52eaf2014-04-04 17:50:18 +0200949 }
950}
951
Ian Rogers62d6c772013-02-27 08:32:07 -0800952void Instrumentation::ExceptionCaughtEvent(Thread* thread, const ThrowLocation& throw_location,
Brian Carlstromea46f952013-07-30 01:26:50 -0700953 mirror::ArtMethod* catch_method,
Ian Rogers62d6c772013-02-27 08:32:07 -0800954 uint32_t catch_dex_pc,
Sebastien Hertz947ff082013-09-17 14:10:13 +0200955 mirror::Throwable* exception_object) const {
Sebastien Hertz9f102032014-05-23 08:59:42 +0200956 if (HasExceptionCaughtListeners()) {
957 DCHECK_EQ(thread->GetException(nullptr), exception_object);
958 bool is_exception_reported = thread->IsExceptionReportedToInstrumentation();
Jeff Haoc0bd4da2013-04-11 15:52:28 -0700959 thread->ClearException();
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200960 std::shared_ptr<std::list<InstrumentationListener*>> original(exception_caught_listeners_);
961 for (InstrumentationListener* listener : *original.get()) {
962 listener->ExceptionCaught(thread, throw_location, catch_method, catch_dex_pc,
963 exception_object);
Ian Rogers62d6c772013-02-27 08:32:07 -0800964 }
Jeff Haoc0bd4da2013-04-11 15:52:28 -0700965 thread->SetException(throw_location, exception_object);
Sebastien Hertz9f102032014-05-23 08:59:42 +0200966 thread->SetExceptionReportedToInstrumentation(is_exception_reported);
Ian Rogers62d6c772013-02-27 08:32:07 -0800967 }
968}
969
970static void CheckStackDepth(Thread* self, const InstrumentationStackFrame& instrumentation_frame,
971 int delta)
972 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
973 size_t frame_id = StackVisitor::ComputeNumFrames(self) + delta;
974 if (frame_id != instrumentation_frame.frame_id_) {
975 LOG(ERROR) << "Expected frame_id=" << frame_id << " but found "
976 << instrumentation_frame.frame_id_;
977 StackVisitor::DescribeStack(self);
978 CHECK_EQ(frame_id, instrumentation_frame.frame_id_);
979 }
980}
981
982void Instrumentation::PushInstrumentationStackFrame(Thread* self, mirror::Object* this_object,
Brian Carlstromea46f952013-07-30 01:26:50 -0700983 mirror::ArtMethod* method,
Jeff Hao9a916d32013-06-27 18:45:37 -0700984 uintptr_t lr, bool interpreter_entry) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800985 // We have a callee-save frame meaning this value is guaranteed to never be 0.
986 size_t frame_id = StackVisitor::ComputeNumFrames(self);
987 std::deque<instrumentation::InstrumentationStackFrame>* stack = self->GetInstrumentationStack();
988 if (kVerboseInstrumentation) {
Brian Carlstrom2d888622013-07-18 17:02:00 -0700989 LOG(INFO) << "Entering " << PrettyMethod(method) << " from PC " << reinterpret_cast<void*>(lr);
Ian Rogers62d6c772013-02-27 08:32:07 -0800990 }
991 instrumentation::InstrumentationStackFrame instrumentation_frame(this_object, method, lr,
Jeff Hao9a916d32013-06-27 18:45:37 -0700992 frame_id, interpreter_entry);
Ian Rogers62d6c772013-02-27 08:32:07 -0800993 stack->push_front(instrumentation_frame);
994
Sebastien Hertz320deb22014-06-11 19:45:05 +0200995 if (!interpreter_entry) {
996 MethodEnterEvent(self, this_object, method, 0);
997 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800998}
999
Andreas Gamped58342c2014-06-05 14:18:08 -07001000TwoWordReturn Instrumentation::PopInstrumentationStackFrame(Thread* self, uintptr_t* return_pc,
1001 uint64_t gpr_result,
1002 uint64_t fpr_result) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001003 // Do the pop.
1004 std::deque<instrumentation::InstrumentationStackFrame>* stack = self->GetInstrumentationStack();
1005 CHECK_GT(stack->size(), 0U);
1006 InstrumentationStackFrame instrumentation_frame = stack->front();
1007 stack->pop_front();
1008
1009 // Set return PC and check the sanity of the stack.
1010 *return_pc = instrumentation_frame.return_pc_;
1011 CheckStackDepth(self, instrumentation_frame, 0);
Ian Rogers1d8cdbc2014-09-22 22:51:09 -07001012 self->VerifyStack();
Ian Rogers62d6c772013-02-27 08:32:07 -08001013
Brian Carlstromea46f952013-07-30 01:26:50 -07001014 mirror::ArtMethod* method = instrumentation_frame.method_;
Mathieu Chartierbfd9a432014-05-21 17:43:44 -07001015 uint32_t length;
1016 char return_shorty = method->GetShorty(&length)[0];
Ian Rogers62d6c772013-02-27 08:32:07 -08001017 JValue return_value;
1018 if (return_shorty == 'V') {
1019 return_value.SetJ(0);
1020 } else if (return_shorty == 'F' || return_shorty == 'D') {
1021 return_value.SetJ(fpr_result);
1022 } else {
1023 return_value.SetJ(gpr_result);
1024 }
1025 // TODO: improve the dex pc information here, requires knowledge of current PC as opposed to
1026 // return_pc.
1027 uint32_t dex_pc = DexFile::kDexNoIndex;
1028 mirror::Object* this_object = instrumentation_frame.this_object_;
Sebastien Hertz320deb22014-06-11 19:45:05 +02001029 if (!instrumentation_frame.interpreter_entry_) {
1030 MethodExitEvent(self, this_object, instrumentation_frame.method_, dex_pc, return_value);
1031 }
jeffhao725a9572012-11-13 18:20:12 -08001032
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001033 // Deoptimize if the caller needs to continue execution in the interpreter. Do nothing if we get
1034 // back to an upcall.
1035 NthCallerVisitor visitor(self, 1, true);
1036 visitor.WalkStack(true);
Sebastien Hertz270a0e12015-01-16 19:49:09 +01001037 bool deoptimize = (visitor.caller != nullptr) &&
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001038 (interpreter_stubs_installed_ || IsDeoptimized(visitor.caller));
Ian Rogers62d6c772013-02-27 08:32:07 -08001039 if (deoptimize) {
1040 if (kVerboseInstrumentation) {
Sebastien Hertz270a0e12015-01-16 19:49:09 +01001041 LOG(INFO) << StringPrintf("Deoptimizing %s by returning from %s with result %#" PRIx64 " in ",
1042 PrettyMethod(visitor.caller).c_str(),
1043 PrettyMethod(method).c_str(),
1044 return_value.GetJ()) << *self;
Ian Rogers62d6c772013-02-27 08:32:07 -08001045 }
1046 self->SetDeoptimizationReturnValue(return_value);
Andreas Gamped58342c2014-06-05 14:18:08 -07001047 return GetTwoWordSuccessValue(*return_pc,
1048 reinterpret_cast<uintptr_t>(GetQuickDeoptimizationEntryPoint()));
Ian Rogers62d6c772013-02-27 08:32:07 -08001049 } else {
1050 if (kVerboseInstrumentation) {
Brian Carlstrom2d888622013-07-18 17:02:00 -07001051 LOG(INFO) << "Returning from " << PrettyMethod(method)
1052 << " to PC " << reinterpret_cast<void*>(*return_pc);
Ian Rogers62d6c772013-02-27 08:32:07 -08001053 }
Andreas Gamped58342c2014-06-05 14:18:08 -07001054 return GetTwoWordSuccessValue(0, *return_pc);
Ian Rogers62d6c772013-02-27 08:32:07 -08001055 }
jeffhao725a9572012-11-13 18:20:12 -08001056}
1057
Ian Rogers62d6c772013-02-27 08:32:07 -08001058void Instrumentation::PopMethodForUnwind(Thread* self, bool is_deoptimization) const {
1059 // Do the pop.
1060 std::deque<instrumentation::InstrumentationStackFrame>* stack = self->GetInstrumentationStack();
1061 CHECK_GT(stack->size(), 0U);
1062 InstrumentationStackFrame instrumentation_frame = stack->front();
1063 // TODO: bring back CheckStackDepth(self, instrumentation_frame, 2);
1064 stack->pop_front();
1065
Brian Carlstromea46f952013-07-30 01:26:50 -07001066 mirror::ArtMethod* method = instrumentation_frame.method_;
Ian Rogers62d6c772013-02-27 08:32:07 -08001067 if (is_deoptimization) {
1068 if (kVerboseInstrumentation) {
1069 LOG(INFO) << "Popping for deoptimization " << PrettyMethod(method);
1070 }
1071 } else {
1072 if (kVerboseInstrumentation) {
1073 LOG(INFO) << "Popping for unwind " << PrettyMethod(method);
1074 }
1075
1076 // Notify listeners of method unwind.
1077 // TODO: improve the dex pc information here, requires knowledge of current PC as opposed to
1078 // return_pc.
1079 uint32_t dex_pc = DexFile::kDexNoIndex;
1080 MethodUnwindEvent(self, instrumentation_frame.this_object_, method, dex_pc);
1081 }
1082}
1083
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -07001084void Instrumentation::VisitRoots(RootCallback* callback, void* arg) {
1085 WriterMutexLock mu(Thread::Current(), deoptimized_methods_lock_);
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -07001086 if (IsDeoptimizedMethodsEmpty()) {
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -07001087 return;
1088 }
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -07001089 for (auto pair : deoptimized_methods_) {
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -08001090 pair.second.VisitRoot(callback, arg, RootInfo(kRootVMInternal));
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -07001091 }
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -07001092}
1093
Ian Rogers62d6c772013-02-27 08:32:07 -08001094std::string InstrumentationStackFrame::Dump() const {
1095 std::ostringstream os;
1096 os << "Frame " << frame_id_ << " " << PrettyMethod(method_) << ":"
1097 << reinterpret_cast<void*>(return_pc_) << " this=" << reinterpret_cast<void*>(this_object_);
1098 return os.str();
1099}
1100
1101} // namespace instrumentation
jeffhao725a9572012-11-13 18:20:12 -08001102} // namespace art