blob: 76065a3bf7f97cf39aec84f6effba110ac9cb917 [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
Alex Lightb7c640d2019-03-20 15:52:13 -070019#include <functional>
20#include <optional>
Ian Rogersc7dd2952014-10-21 23:31:19 -070021#include <sstream>
22
Andreas Gampec7d878d2018-11-19 18:42:06 +000023#include <android-base/logging.h>
24
Ian Rogerse63db272014-07-15 15:36:11 -070025#include "arch/context.h"
Alex Lightd7661582017-05-01 13:48:16 -070026#include "art_field-inl.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070027#include "art_method-inl.h"
David Sehrc431b9d2018-03-02 12:01:51 -080028#include "base/atomic.h"
Andreas Gampe8228cdf2017-05-30 15:03:54 -070029#include "base/callee_save_type.h"
jeffhao725a9572012-11-13 18:20:12 -080030#include "class_linker.h"
31#include "debugger.h"
David Sehr9e734c72018-01-04 17:56:19 -080032#include "dex/dex_file-inl.h"
33#include "dex/dex_file_types.h"
34#include "dex/dex_instruction-inl.h"
Mathieu Chartierd8891782014-03-02 13:28:37 -080035#include "entrypoints/quick/quick_alloc_entrypoints.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070036#include "entrypoints/quick/quick_entrypoints.h"
Ian Rogers6f3dbba2014-10-14 17:41:57 -070037#include "entrypoints/runtime_asm_entrypoints.h"
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -070038#include "gc_root-inl.h"
Sebastien Hertz138dbfc2013-12-04 18:15:25 +010039#include "interpreter/interpreter.h"
Mingyao Yang2ee17902017-08-30 11:37:08 -070040#include "interpreter/interpreter_common.h"
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080041#include "jit/jit.h"
42#include "jit/jit_code_cache.h"
Alex Lightd7661582017-05-01 13:48:16 -070043#include "jvalue-inl.h"
Alex Lightb7c640d2019-03-20 15:52:13 -070044#include "jvalue.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080045#include "mirror/class-inl.h"
46#include "mirror/dex_cache.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070047#include "mirror/object-inl.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070048#include "mirror/object_array-inl.h"
Ian Rogers62d6c772013-02-27 08:32:07 -080049#include "nth_caller_visitor.h"
Nicolas Geoffray524e7ea2015-10-16 17:13:34 +010050#include "oat_quick_method_header.h"
David Srbecky28f6cff2018-10-16 15:07:28 +010051#include "runtime-inl.h"
jeffhao725a9572012-11-13 18:20:12 -080052#include "thread.h"
53#include "thread_list.h"
jeffhao725a9572012-11-13 18:20:12 -080054
55namespace art {
Ian Rogers62d6c772013-02-27 08:32:07 -080056namespace instrumentation {
jeffhao725a9572012-11-13 18:20:12 -080057
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020058constexpr bool kVerboseInstrumentation = false;
Sebastien Hertz5bfd5c92013-11-15 11:36:07 +010059
Alex Lightb7c640d2019-03-20 15:52:13 -070060void InstrumentationListener::MethodExited(
61 Thread* thread,
62 Handle<mirror::Object> this_object,
63 ArtMethod* method,
64 uint32_t dex_pc,
65 OptionalFrame frame,
66 MutableHandle<mirror::Object>& return_value) {
Alex Lightd7661582017-05-01 13:48:16 -070067 DCHECK_EQ(method->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetReturnTypePrimitive(),
68 Primitive::kPrimNot);
Alex Lightb7c640d2019-03-20 15:52:13 -070069 const void* original_ret = return_value.Get();
Alex Lightd7661582017-05-01 13:48:16 -070070 JValue v;
71 v.SetL(return_value.Get());
Alex Lightb7c640d2019-03-20 15:52:13 -070072 MethodExited(thread, this_object, method, dex_pc, frame, v);
73 DCHECK(original_ret == v.GetL()) << "Return value changed";
Alex Lightd7661582017-05-01 13:48:16 -070074}
75
76void InstrumentationListener::FieldWritten(Thread* thread,
77 Handle<mirror::Object> this_object,
78 ArtMethod* method,
79 uint32_t dex_pc,
80 ArtField* field,
81 Handle<mirror::Object> field_value) {
82 DCHECK(!field->IsPrimitiveType());
83 JValue v;
84 v.SetL(field_value.Get());
85 FieldWritten(thread, this_object, method, dex_pc, field, v);
86}
87
Nicolas Geoffray8e5bd182015-05-06 11:34:34 +010088// Instrumentation works on non-inlined frames by updating returned PCs
89// of compiled frames.
90static constexpr StackVisitor::StackWalkKind kInstrumentationStackWalk =
91 StackVisitor::StackWalkKind::kSkipInlinedFrames;
92
Mathieu Chartiere0671ce2015-07-28 17:23:28 -070093class InstallStubsClassVisitor : public ClassVisitor {
94 public:
95 explicit InstallStubsClassVisitor(Instrumentation* instrumentation)
96 : instrumentation_(instrumentation) {}
97
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010098 bool operator()(ObjPtr<mirror::Class> klass) override REQUIRES(Locks::mutator_lock_) {
Mathieu Chartier28357fa2016-10-18 16:27:40 -070099 instrumentation_->InstallStubsForClass(klass.Ptr());
Mathieu Chartiere0671ce2015-07-28 17:23:28 -0700100 return true; // we visit all classes.
101 }
102
103 private:
104 Instrumentation* const instrumentation_;
105};
106
Alex Light2c8206f2018-06-08 14:51:09 -0700107InstrumentationStackPopper::InstrumentationStackPopper(Thread* self)
108 : self_(self),
109 instrumentation_(Runtime::Current()->GetInstrumentation()),
110 frames_to_remove_(0) {}
111
112InstrumentationStackPopper::~InstrumentationStackPopper() {
113 std::deque<instrumentation::InstrumentationStackFrame>* stack = self_->GetInstrumentationStack();
114 for (size_t i = 0; i < frames_to_remove_; i++) {
115 stack->pop_front();
116 }
117}
118
119bool InstrumentationStackPopper::PopFramesTo(uint32_t desired_pops,
120 MutableHandle<mirror::Throwable>& exception) {
121 std::deque<instrumentation::InstrumentationStackFrame>* stack = self_->GetInstrumentationStack();
122 DCHECK_LE(frames_to_remove_, desired_pops);
123 DCHECK_GE(stack->size(), desired_pops);
124 DCHECK(!self_->IsExceptionPending());
125 if (!instrumentation_->HasMethodUnwindListeners()) {
126 frames_to_remove_ = desired_pops;
127 return true;
128 }
129 if (kVerboseInstrumentation) {
130 LOG(INFO) << "Popping frames for exception " << exception->Dump();
131 }
132 // The instrumentation events expect the exception to be set.
133 self_->SetException(exception.Get());
134 bool new_exception_thrown = false;
135 for (; frames_to_remove_ < desired_pops && !new_exception_thrown; frames_to_remove_++) {
136 InstrumentationStackFrame frame = stack->at(frames_to_remove_);
137 ArtMethod* method = frame.method_;
138 // Notify listeners of method unwind.
139 // TODO: improve the dex_pc information here.
140 uint32_t dex_pc = dex::kDexNoIndex;
141 if (kVerboseInstrumentation) {
142 LOG(INFO) << "Popping for unwind " << method->PrettyMethod();
143 }
144 if (!method->IsRuntimeMethod() && !frame.interpreter_entry_) {
145 instrumentation_->MethodUnwindEvent(self_, frame.this_object_, method, dex_pc);
146 new_exception_thrown = self_->GetException() != exception.Get();
147 }
148 }
149 exception.Assign(self_->GetException());
150 self_->ClearException();
151 if (kVerboseInstrumentation && new_exception_thrown) {
152 LOG(INFO) << "Failed to pop " << (desired_pops - frames_to_remove_)
153 << " frames due to new exception";
154 }
155 return !new_exception_thrown;
156}
Ian Rogers62d6c772013-02-27 08:32:07 -0800157
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -0700158Instrumentation::Instrumentation()
Nicolas Geoffray5a23d2e2015-11-03 18:58:57 +0000159 : instrumentation_stubs_installed_(false),
160 entry_exit_stubs_installed_(false),
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -0700161 interpreter_stubs_installed_(false),
Nicolas Geoffray5a23d2e2015-11-03 18:58:57 +0000162 interpret_only_(false),
163 forced_interpret_only_(false),
164 have_method_entry_listeners_(false),
165 have_method_exit_listeners_(false),
166 have_method_unwind_listeners_(false),
167 have_dex_pc_listeners_(false),
168 have_field_read_listeners_(false),
169 have_field_write_listeners_(false),
Alex Light6e1607e2017-08-23 10:06:18 -0700170 have_exception_thrown_listeners_(false),
Alex Lighte814f9d2017-07-31 16:14:39 -0700171 have_watched_frame_pop_listeners_(false),
Nicolas Geoffray81f0f952016-01-20 16:25:19 +0000172 have_branch_listeners_(false),
Alex Light9fb1ab12017-09-05 09:32:49 -0700173 have_exception_handled_listeners_(false),
Andreas Gampe7e56a072018-11-29 10:40:06 -0800174 deoptimized_methods_lock_(new ReaderWriterMutex("deoptimized methods lock",
175 kGenericBottomLock)),
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -0700176 deoptimization_enabled_(false),
177 interpreter_handler_table_(kMainHandlerTable),
Mathieu Chartier50e93312016-03-16 11:25:29 -0700178 quick_alloc_entry_points_instrumentation_counter_(0),
Alex Light40607862019-05-06 18:16:24 +0000179 alloc_entrypoints_instrumented_(false),
180 can_use_instrumentation_trampolines_(true) {
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -0700181}
182
Vladimir Marko19711d42019-04-12 14:05:34 +0100183void Instrumentation::InstallStubsForClass(ObjPtr<mirror::Class> klass) {
Vladimir Marko72ab6842017-01-20 19:32:50 +0000184 if (!klass->IsResolved()) {
Sebastien Hertza8a697f2015-01-15 12:28:47 +0100185 // We need the class to be resolved to install/uninstall stubs. Otherwise its methods
186 // could not be initialized or linked with regards to class inheritance.
Vladimir Marko72ab6842017-01-20 19:32:50 +0000187 } else if (klass->IsErroneousResolved()) {
188 // We can't execute code in a erroneous class: do nothing.
Sebastien Hertza8a697f2015-01-15 12:28:47 +0100189 } else {
Andreas Gampe542451c2016-07-26 09:02:02 -0700190 for (ArtMethod& method : klass->GetMethods(kRuntimePointerSize)) {
Alex Light51a64d52015-12-17 13:55:59 -0800191 InstallStubsForMethod(&method);
Sebastien Hertza8a697f2015-01-15 12:28:47 +0100192 }
jeffhao725a9572012-11-13 18:20:12 -0800193 }
jeffhao725a9572012-11-13 18:20:12 -0800194}
195
Mathieu Chartiere401d142015-04-22 13:56:20 -0700196static void UpdateEntrypoints(ArtMethod* method, const void* quick_code)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700197 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffrayd5a95872019-08-12 13:24:07 +0100198 if (kIsDebugBuild) {
199 jit::Jit* jit = Runtime::Current()->GetJit();
200 if (jit != nullptr && jit->GetCodeCache()->ContainsPc(quick_code)) {
201 // Ensure we always have the thumb entrypoint for JIT on arm32.
202 if (kRuntimeISA == InstructionSet::kArm) {
203 CHECK_EQ(reinterpret_cast<uintptr_t>(quick_code) & 1, 1u);
204 }
205 }
206 }
Ian Rogersef7d42f2014-01-06 12:55:46 -0800207 method->SetEntryPointFromQuickCompiledCode(quick_code);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100208}
209
Alex Light0fa17862017-10-24 13:43:05 -0700210bool Instrumentation::NeedDebugVersionFor(ArtMethod* method) const
211 REQUIRES_SHARED(Locks::mutator_lock_) {
Alex Lightf2858632018-04-02 11:28:50 -0700212 art::Runtime* runtime = Runtime::Current();
213 // If anything says we need the debug version or we are debuggable we will need the debug version
214 // of the method.
215 return (runtime->GetRuntimeCallbacks()->MethodNeedsDebugVersion(method) ||
216 runtime->IsJavaDebuggable()) &&
Mingyao Yang6ea1a0e2016-01-29 12:12:49 -0800217 !method->IsNative() &&
Alex Lightf2858632018-04-02 11:28:50 -0700218 !method->IsProxyMethod();
Mingyao Yang6ea1a0e2016-01-29 12:12:49 -0800219}
220
Mathieu Chartiere401d142015-04-22 13:56:20 -0700221void Instrumentation::InstallStubsForMethod(ArtMethod* method) {
Alex Light9139e002015-10-09 15:59:48 -0700222 if (!method->IsInvokable() || method->IsProxyMethod()) {
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100223 // Do not change stubs for these methods.
224 return;
225 }
Jeff Hao56802772014-08-19 10:17:36 -0700226 // Don't stub Proxy.<init>. Note that the Proxy class itself is not a proxy class.
Alex Light6cae5ea2018-06-07 17:07:02 -0700227 // TODO We should remove the need for this since it means we cannot always correctly detect calls
228 // to Proxy.<init>
229 // Annoyingly this can be called before we have actually initialized WellKnownClasses so therefore
230 // we also need to check this based on the declaring-class descriptor. The check is valid because
231 // Proxy only has a single constructor.
232 ArtMethod* well_known_proxy_init = jni::DecodeArtMethod(
233 WellKnownClasses::java_lang_reflect_Proxy_init);
234 if ((LIKELY(well_known_proxy_init != nullptr) && UNLIKELY(method == well_known_proxy_init)) ||
235 UNLIKELY(method->IsConstructor() &&
236 method->GetDeclaringClass()->DescriptorEquals("Ljava/lang/reflect/Proxy;"))) {
Jeff Haodb8a6642014-08-14 17:18:52 -0700237 return;
238 }
Ian Rogersef7d42f2014-01-06 12:55:46 -0800239 const void* new_quick_code;
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100240 bool uninstall = !entry_exit_stubs_installed_ && !interpreter_stubs_installed_;
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800241 Runtime* const runtime = Runtime::Current();
242 ClassLinker* const class_linker = runtime->GetClassLinker();
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100243 bool is_class_initialized = method->GetDeclaringClass()->IsInitialized();
244 if (uninstall) {
245 if ((forced_interpret_only_ || IsDeoptimized(method)) && !method->IsNative()) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800246 new_quick_code = GetQuickToInterpreterBridge();
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100247 } else if (is_class_initialized || !method->IsStatic() || method->IsConstructor()) {
Alex Light3e36a9c2018-06-19 09:45:05 -0700248 new_quick_code = GetCodeForInvoke(method);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100249 } else {
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700250 new_quick_code = GetQuickResolutionStub();
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100251 }
252 } else { // !uninstall
Sebastien Hertzbae182c2013-12-17 10:42:03 +0100253 if ((interpreter_stubs_installed_ || forced_interpret_only_ || IsDeoptimized(method)) &&
254 !method->IsNative()) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800255 new_quick_code = GetQuickToInterpreterBridge();
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100256 } else {
257 // Do not overwrite resolution trampoline. When the trampoline initializes the method's
258 // class, all its static methods code will be set to the instrumentation entry point.
259 // For more details, see ClassLinker::FixupStaticTrampolines.
260 if (is_class_initialized || !method->IsStatic() || method->IsConstructor()) {
Alex Light2d441b12018-06-08 15:33:21 -0700261 if (entry_exit_stubs_installed_) {
262 // This needs to be checked first since the instrumentation entrypoint will be able to
263 // find the actual JIT compiled code that corresponds to this method.
Ian Rogersef7d42f2014-01-06 12:55:46 -0800264 new_quick_code = GetQuickInstrumentationEntryPoint();
Alex Light2d441b12018-06-08 15:33:21 -0700265 } else if (NeedDebugVersionFor(method)) {
266 // It would be great to search the JIT for its implementation here but we cannot due to
267 // the locks we hold. Instead just set to the interpreter bridge and that code will search
268 // the JIT when it gets called and replace the entrypoint then.
269 new_quick_code = GetQuickToInterpreterBridge();
Nicolas Geoffraya0619e22016-12-20 13:57:43 +0000270 } else {
Alex Lightfc49fec2018-01-16 22:28:36 +0000271 new_quick_code = class_linker->GetQuickOatCodeFor(method);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100272 }
273 } else {
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700274 new_quick_code = GetQuickResolutionStub();
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100275 }
276 }
277 }
Elliott Hughes956af0f2014-12-11 14:34:28 -0800278 UpdateEntrypoints(method, new_quick_code);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100279}
280
Ian Rogers62d6c772013-02-27 08:32:07 -0800281// Places the instrumentation exit pc as the return PC for every quick frame. This also allows
282// deoptimization of quick frames to interpreter frames.
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100283// Since we may already have done this previously, we need to push new instrumentation frame before
284// existing instrumentation frames.
Ian Rogers62d6c772013-02-27 08:32:07 -0800285static void InstrumentationInstallStack(Thread* thread, void* arg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700286 REQUIRES_SHARED(Locks::mutator_lock_) {
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100287 struct InstallStackVisitor final : public StackVisitor {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800288 InstallStackVisitor(Thread* thread_in, Context* context, uintptr_t instrumentation_exit_pc)
Nicolas Geoffray8e5bd182015-05-06 11:34:34 +0100289 : StackVisitor(thread_in, context, kInstrumentationStackWalk),
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800290 instrumentation_stack_(thread_in->GetInstrumentationStack()),
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100291 instrumentation_exit_pc_(instrumentation_exit_pc),
Alex Lighte9278662018-03-08 16:55:58 -0800292 reached_existing_instrumentation_frames_(false), instrumentation_stack_depth_(0),
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100293 last_return_pc_(0) {
294 }
jeffhao725a9572012-11-13 18:20:12 -0800295
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100296 bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700297 ArtMethod* m = GetMethod();
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700298 if (m == nullptr) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800299 if (kVerboseInstrumentation) {
300 LOG(INFO) << " Skipping upcall. Frame " << GetFrameId();
301 }
302 last_return_pc_ = 0;
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700303 return true; // Ignore upcalls.
Ian Rogers306057f2012-11-26 12:45:53 -0800304 }
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700305 if (GetCurrentQuickFrame() == nullptr) {
Elliott Hughes956af0f2014-12-11 14:34:28 -0800306 bool interpreter_frame = true;
Vladimir Markoabedfca2019-05-23 14:07:47 +0100307 InstrumentationStackFrame instrumentation_frame(GetThisObject().Ptr(),
308 m,
309 /*return_pc=*/ 0,
310 GetFrameId(),
Sebastien Hertz320deb22014-06-11 19:45:05 +0200311 interpreter_frame);
Jeff Haoa15a81b2014-05-27 18:25:47 -0700312 if (kVerboseInstrumentation) {
313 LOG(INFO) << "Pushing shadow frame " << instrumentation_frame.Dump();
314 }
315 shadow_stack_.push_back(instrumentation_frame);
316 return true; // Continue.
317 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800318 uintptr_t return_pc = GetReturnPc();
Sebastien Hertz320deb22014-06-11 19:45:05 +0200319 if (kVerboseInstrumentation) {
320 LOG(INFO) << " Installing exit stub in " << DescribeLocation();
321 }
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100322 if (return_pc == instrumentation_exit_pc_) {
Mingyao Yang2ee17902017-08-30 11:37:08 -0700323 CHECK_LT(instrumentation_stack_depth_, instrumentation_stack_->size());
324
325 if (m->IsRuntimeMethod()) {
326 const InstrumentationStackFrame& frame =
Vladimir Marko35d5b8a2018-07-03 09:18:32 +0100327 (*instrumentation_stack_)[instrumentation_stack_depth_];
Mingyao Yang2ee17902017-08-30 11:37:08 -0700328 if (frame.interpreter_entry_) {
329 // This instrumentation frame is for an interpreter bridge and is
330 // pushed when executing the instrumented interpreter bridge. So method
331 // enter event must have been reported. However we need to push a DEX pc
332 // into the dex_pcs_ list to match size of instrumentation stack.
Andreas Gampee2abbc62017-09-15 11:59:26 -0700333 uint32_t dex_pc = dex::kDexNoIndex;
Mingyao Yang2ee17902017-08-30 11:37:08 -0700334 dex_pcs_.push_back(dex_pc);
335 last_return_pc_ = frame.return_pc_;
336 ++instrumentation_stack_depth_;
337 return true;
338 }
339 }
340
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100341 // We've reached a frame which has already been installed with instrumentation exit stub.
Alex Light74c91c92018-03-08 14:01:44 -0800342 // We should have already installed instrumentation or be interpreter on previous frames.
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100343 reached_existing_instrumentation_frames_ = true;
344
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200345 const InstrumentationStackFrame& frame =
Vladimir Marko35d5b8a2018-07-03 09:18:32 +0100346 (*instrumentation_stack_)[instrumentation_stack_depth_];
Alex Lightfc81d802018-12-07 13:39:05 -0800347 CHECK_EQ(m->GetNonObsoleteMethod(), frame.method_->GetNonObsoleteMethod())
348 << "Expected " << ArtMethod::PrettyMethod(m)
349 << ", Found " << ArtMethod::PrettyMethod(frame.method_);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100350 return_pc = frame.return_pc_;
351 if (kVerboseInstrumentation) {
352 LOG(INFO) << "Ignoring already instrumented " << frame.Dump();
353 }
354 } else {
355 CHECK_NE(return_pc, 0U);
Alex Light74c91c92018-03-08 14:01:44 -0800356 if (UNLIKELY(reached_existing_instrumentation_frames_ && !m->IsRuntimeMethod())) {
357 // We already saw an existing instrumentation frame so this should be a runtime-method
358 // inserted by the interpreter or runtime.
Alex Lighte9278662018-03-08 16:55:58 -0800359 std::string thread_name;
360 GetThread()->GetThreadName(thread_name);
361 uint32_t dex_pc = dex::kDexNoIndex;
362 if (last_return_pc_ != 0 &&
363 GetCurrentOatQuickMethodHeader() != nullptr) {
364 dex_pc = GetCurrentOatQuickMethodHeader()->ToDexPc(m, last_return_pc_);
365 }
Alex Light74c91c92018-03-08 14:01:44 -0800366 LOG(FATAL) << "While walking " << thread_name << " found unexpected non-runtime method"
367 << " without instrumentation exit return or interpreter frame."
Alex Lighte9278662018-03-08 16:55:58 -0800368 << " method is " << GetMethod()->PrettyMethod()
369 << " return_pc is " << std::hex << return_pc
370 << " dex pc: " << dex_pc;
371 UNREACHABLE();
372 }
Mingyao Yang2ee17902017-08-30 11:37:08 -0700373 InstrumentationStackFrame instrumentation_frame(
Vladimir Markoabedfca2019-05-23 14:07:47 +0100374 m->IsRuntimeMethod() ? nullptr : GetThisObject().Ptr(),
Mingyao Yang2ee17902017-08-30 11:37:08 -0700375 m,
376 return_pc,
377 GetFrameId(), // A runtime method still gets a frame id.
378 false);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100379 if (kVerboseInstrumentation) {
380 LOG(INFO) << "Pushing frame " << instrumentation_frame.Dump();
381 }
382
Sebastien Hertz320deb22014-06-11 19:45:05 +0200383 // Insert frame at the right position so we do not corrupt the instrumentation stack.
384 // Instrumentation stack frames are in descending frame id order.
385 auto it = instrumentation_stack_->begin();
386 for (auto end = instrumentation_stack_->end(); it != end; ++it) {
387 const InstrumentationStackFrame& current = *it;
388 if (instrumentation_frame.frame_id_ >= current.frame_id_) {
389 break;
390 }
391 }
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100392 instrumentation_stack_->insert(it, instrumentation_frame);
393 SetReturnPc(instrumentation_exit_pc_);
Ian Rogers62d6c772013-02-27 08:32:07 -0800394 }
Andreas Gampee2abbc62017-09-15 11:59:26 -0700395 uint32_t dex_pc = dex::kDexNoIndex;
Mingyao Yang2ee17902017-08-30 11:37:08 -0700396 if (last_return_pc_ != 0 &&
397 GetCurrentOatQuickMethodHeader() != nullptr) {
398 dex_pc = GetCurrentOatQuickMethodHeader()->ToDexPc(m, last_return_pc_);
399 }
400 dex_pcs_.push_back(dex_pc);
Ian Rogers62d6c772013-02-27 08:32:07 -0800401 last_return_pc_ = return_pc;
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100402 ++instrumentation_stack_depth_;
Ian Rogers306057f2012-11-26 12:45:53 -0800403 return true; // Continue.
404 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800405 std::deque<InstrumentationStackFrame>* const instrumentation_stack_;
Jeff Haoa15a81b2014-05-27 18:25:47 -0700406 std::vector<InstrumentationStackFrame> shadow_stack_;
Ian Rogers62d6c772013-02-27 08:32:07 -0800407 std::vector<uint32_t> dex_pcs_;
Ian Rogers306057f2012-11-26 12:45:53 -0800408 const uintptr_t instrumentation_exit_pc_;
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100409 bool reached_existing_instrumentation_frames_;
410 size_t instrumentation_stack_depth_;
Ian Rogers62d6c772013-02-27 08:32:07 -0800411 uintptr_t last_return_pc_;
Ian Rogers306057f2012-11-26 12:45:53 -0800412 };
Ian Rogers62d6c772013-02-27 08:32:07 -0800413 if (kVerboseInstrumentation) {
414 std::string thread_name;
415 thread->GetThreadName(thread_name);
416 LOG(INFO) << "Installing exit stubs in " << thread_name;
Ian Rogers306057f2012-11-26 12:45:53 -0800417 }
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100418
419 Instrumentation* instrumentation = reinterpret_cast<Instrumentation*>(arg);
Ian Rogers700a4022014-05-19 16:49:03 -0700420 std::unique_ptr<Context> context(Context::Create());
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700421 uintptr_t instrumentation_exit_pc = reinterpret_cast<uintptr_t>(GetQuickInstrumentationExitPc());
Sebastien Hertz11d40c22014-02-19 18:00:17 +0100422 InstallStackVisitor visitor(thread, context.get(), instrumentation_exit_pc);
Ian Rogers62d6c772013-02-27 08:32:07 -0800423 visitor.WalkStack(true);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100424 CHECK_EQ(visitor.dex_pcs_.size(), thread->GetInstrumentationStack()->size());
Ian Rogers62d6c772013-02-27 08:32:07 -0800425
Sebastien Hertz7ec2f1c2014-03-27 20:06:47 +0100426 if (instrumentation->ShouldNotifyMethodEnterExitEvents()) {
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100427 // Create method enter events for all methods currently on the thread's stack. We only do this
428 // if no debugger is attached to prevent from posting events twice.
Jeff Haoa15a81b2014-05-27 18:25:47 -0700429 auto ssi = visitor.shadow_stack_.rbegin();
430 for (auto isi = thread->GetInstrumentationStack()->rbegin(),
431 end = thread->GetInstrumentationStack()->rend(); isi != end; ++isi) {
432 while (ssi != visitor.shadow_stack_.rend() && (*ssi).frame_id_ < (*isi).frame_id_) {
433 instrumentation->MethodEnterEvent(thread, (*ssi).this_object_, (*ssi).method_, 0);
434 ++ssi;
435 }
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100436 uint32_t dex_pc = visitor.dex_pcs_.back();
437 visitor.dex_pcs_.pop_back();
Alex Lightdc5423f2018-06-08 10:43:38 -0700438 if (!isi->interpreter_entry_ && !isi->method_->IsRuntimeMethod()) {
Sebastien Hertz320deb22014-06-11 19:45:05 +0200439 instrumentation->MethodEnterEvent(thread, (*isi).this_object_, (*isi).method_, dex_pc);
440 }
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100441 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800442 }
443 thread->VerifyStack();
Ian Rogers306057f2012-11-26 12:45:53 -0800444}
445
Mingyao Yang99170c62015-07-06 11:10:37 -0700446void Instrumentation::InstrumentThreadStack(Thread* thread) {
447 instrumentation_stubs_installed_ = true;
448 InstrumentationInstallStack(thread, this);
449}
450
Ian Rogers62d6c772013-02-27 08:32:07 -0800451// Removes the instrumentation exit pc as the return PC for every quick frame.
452static void InstrumentationRestoreStack(Thread* thread, void* arg)
Nicolas Geoffray5a23d2e2015-11-03 18:58:57 +0000453 REQUIRES(Locks::mutator_lock_) {
454 Locks::mutator_lock_->AssertExclusiveHeld(Thread::Current());
455
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100456 struct RestoreStackVisitor final : public StackVisitor {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800457 RestoreStackVisitor(Thread* thread_in, uintptr_t instrumentation_exit_pc,
Ian Rogers62d6c772013-02-27 08:32:07 -0800458 Instrumentation* instrumentation)
Nicolas Geoffray8e5bd182015-05-06 11:34:34 +0100459 : StackVisitor(thread_in, nullptr, kInstrumentationStackWalk),
460 thread_(thread_in),
Ian Rogers62d6c772013-02-27 08:32:07 -0800461 instrumentation_exit_pc_(instrumentation_exit_pc),
462 instrumentation_(instrumentation),
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800463 instrumentation_stack_(thread_in->GetInstrumentationStack()),
Ian Rogers62d6c772013-02-27 08:32:07 -0800464 frames_removed_(0) {}
Ian Rogers306057f2012-11-26 12:45:53 -0800465
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100466 bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800467 if (instrumentation_stack_->size() == 0) {
jeffhao725a9572012-11-13 18:20:12 -0800468 return false; // Stop.
469 }
Mathieu Chartiere401d142015-04-22 13:56:20 -0700470 ArtMethod* m = GetMethod();
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700471 if (GetCurrentQuickFrame() == nullptr) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800472 if (kVerboseInstrumentation) {
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200473 LOG(INFO) << " Ignoring a shadow frame. Frame " << GetFrameId()
David Sehr709b0702016-10-13 09:12:37 -0700474 << " Method=" << ArtMethod::PrettyMethod(m);
Ian Rogers62d6c772013-02-27 08:32:07 -0800475 }
476 return true; // Ignore shadow frames.
477 }
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700478 if (m == nullptr) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800479 if (kVerboseInstrumentation) {
480 LOG(INFO) << " Skipping upcall. Frame " << GetFrameId();
481 }
Ian Rogers306057f2012-11-26 12:45:53 -0800482 return true; // Ignore upcalls.
483 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800484 bool removed_stub = false;
485 // TODO: make this search more efficient?
Sebastien Hertz7ec2f1c2014-03-27 20:06:47 +0100486 const size_t frameId = GetFrameId();
487 for (const InstrumentationStackFrame& instrumentation_frame : *instrumentation_stack_) {
488 if (instrumentation_frame.frame_id_ == frameId) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800489 if (kVerboseInstrumentation) {
490 LOG(INFO) << " Removing exit stub in " << DescribeLocation();
491 }
Jeff Hao9a916d32013-06-27 18:45:37 -0700492 if (instrumentation_frame.interpreter_entry_) {
Andreas Gampe8228cdf2017-05-30 15:03:54 -0700493 CHECK(m == Runtime::Current()->GetCalleeSaveMethod(CalleeSaveType::kSaveRefsAndArgs));
Jeff Hao9a916d32013-06-27 18:45:37 -0700494 } else {
Alex Lightfc81d802018-12-07 13:39:05 -0800495 CHECK_EQ(m->GetNonObsoleteMethod(),
496 instrumentation_frame.method_->GetNonObsoleteMethod())
497 << ArtMethod::PrettyMethod(m);
Jeff Hao9a916d32013-06-27 18:45:37 -0700498 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800499 SetReturnPc(instrumentation_frame.return_pc_);
Mingyao Yang2ee17902017-08-30 11:37:08 -0700500 if (instrumentation_->ShouldNotifyMethodEnterExitEvents() &&
501 !m->IsRuntimeMethod()) {
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100502 // Create the method exit events. As the methods didn't really exit the result is 0.
503 // We only do this if no debugger is attached to prevent from posting events twice.
Alex Lightb7c640d2019-03-20 15:52:13 -0700504 JValue val;
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100505 instrumentation_->MethodExitEvent(thread_, instrumentation_frame.this_object_, m,
Alex Lightb7c640d2019-03-20 15:52:13 -0700506 GetDexPc(), OptionalFrame{}, val);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100507 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800508 frames_removed_++;
509 removed_stub = true;
510 break;
511 }
512 }
513 if (!removed_stub) {
514 if (kVerboseInstrumentation) {
515 LOG(INFO) << " No exit stub in " << DescribeLocation();
Ian Rogers306057f2012-11-26 12:45:53 -0800516 }
jeffhao725a9572012-11-13 18:20:12 -0800517 }
518 return true; // Continue.
519 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800520 Thread* const thread_;
Ian Rogers306057f2012-11-26 12:45:53 -0800521 const uintptr_t instrumentation_exit_pc_;
Ian Rogers62d6c772013-02-27 08:32:07 -0800522 Instrumentation* const instrumentation_;
523 std::deque<instrumentation::InstrumentationStackFrame>* const instrumentation_stack_;
524 size_t frames_removed_;
jeffhao725a9572012-11-13 18:20:12 -0800525 };
Ian Rogers62d6c772013-02-27 08:32:07 -0800526 if (kVerboseInstrumentation) {
527 std::string thread_name;
528 thread->GetThreadName(thread_name);
529 LOG(INFO) << "Removing exit stubs in " << thread_name;
530 }
531 std::deque<instrumentation::InstrumentationStackFrame>* stack = thread->GetInstrumentationStack();
532 if (stack->size() > 0) {
533 Instrumentation* instrumentation = reinterpret_cast<Instrumentation*>(arg);
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700534 uintptr_t instrumentation_exit_pc =
535 reinterpret_cast<uintptr_t>(GetQuickInstrumentationExitPc());
Ian Rogers62d6c772013-02-27 08:32:07 -0800536 RestoreStackVisitor visitor(thread, instrumentation_exit_pc, instrumentation);
537 visitor.WalkStack(true);
538 CHECK_EQ(visitor.frames_removed_, stack->size());
539 while (stack->size() > 0) {
540 stack->pop_front();
541 }
jeffhao725a9572012-11-13 18:20:12 -0800542 }
543}
544
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200545static bool HasEvent(Instrumentation::InstrumentationEvent expected, uint32_t events) {
546 return (events & expected) != 0;
547}
548
Nicolas Geoffray514a6162015-11-03 11:44:24 +0000549static void PotentiallyAddListenerTo(Instrumentation::InstrumentationEvent event,
550 uint32_t events,
551 std::list<InstrumentationListener*>& list,
552 InstrumentationListener* listener,
553 bool* has_listener)
554 REQUIRES(Locks::mutator_lock_, !Locks::thread_list_lock_, !Locks::classlinker_classes_lock_) {
555 Locks::mutator_lock_->AssertExclusiveHeld(Thread::Current());
556 if (!HasEvent(event, events)) {
557 return;
558 }
559 // If there is a free slot in the list, we insert the listener in that slot.
560 // Otherwise we add it to the end of the list.
561 auto it = std::find(list.begin(), list.end(), nullptr);
562 if (it != list.end()) {
563 *it = listener;
564 } else {
565 list.push_back(listener);
566 }
David Srbecky28f6cff2018-10-16 15:07:28 +0100567 Runtime::DoAndMaybeSwitchInterpreter([=](){ *has_listener = true; });
Nicolas Geoffray514a6162015-11-03 11:44:24 +0000568}
569
Ian Rogers62d6c772013-02-27 08:32:07 -0800570void Instrumentation::AddListener(InstrumentationListener* listener, uint32_t events) {
571 Locks::mutator_lock_->AssertExclusiveHeld(Thread::Current());
Nicolas Geoffray514a6162015-11-03 11:44:24 +0000572 PotentiallyAddListenerTo(kMethodEntered,
573 events,
574 method_entry_listeners_,
575 listener,
576 &have_method_entry_listeners_);
577 PotentiallyAddListenerTo(kMethodExited,
578 events,
579 method_exit_listeners_,
580 listener,
581 &have_method_exit_listeners_);
582 PotentiallyAddListenerTo(kMethodUnwind,
583 events,
584 method_unwind_listeners_,
585 listener,
586 &have_method_unwind_listeners_);
Nicolas Geoffray81f0f952016-01-20 16:25:19 +0000587 PotentiallyAddListenerTo(kBranch,
Nicolas Geoffray514a6162015-11-03 11:44:24 +0000588 events,
Nicolas Geoffray81f0f952016-01-20 16:25:19 +0000589 branch_listeners_,
Nicolas Geoffray514a6162015-11-03 11:44:24 +0000590 listener,
Nicolas Geoffray81f0f952016-01-20 16:25:19 +0000591 &have_branch_listeners_);
Nicolas Geoffray514a6162015-11-03 11:44:24 +0000592 PotentiallyAddListenerTo(kDexPcMoved,
593 events,
594 dex_pc_listeners_,
595 listener,
596 &have_dex_pc_listeners_);
597 PotentiallyAddListenerTo(kFieldRead,
598 events,
599 field_read_listeners_,
600 listener,
601 &have_field_read_listeners_);
602 PotentiallyAddListenerTo(kFieldWritten,
603 events,
604 field_write_listeners_,
605 listener,
606 &have_field_write_listeners_);
Alex Light6e1607e2017-08-23 10:06:18 -0700607 PotentiallyAddListenerTo(kExceptionThrown,
Nicolas Geoffray514a6162015-11-03 11:44:24 +0000608 events,
Alex Light6e1607e2017-08-23 10:06:18 -0700609 exception_thrown_listeners_,
Nicolas Geoffray514a6162015-11-03 11:44:24 +0000610 listener,
Alex Light6e1607e2017-08-23 10:06:18 -0700611 &have_exception_thrown_listeners_);
Alex Lighte814f9d2017-07-31 16:14:39 -0700612 PotentiallyAddListenerTo(kWatchedFramePop,
613 events,
614 watched_frame_pop_listeners_,
615 listener,
616 &have_watched_frame_pop_listeners_);
Alex Light9fb1ab12017-09-05 09:32:49 -0700617 PotentiallyAddListenerTo(kExceptionHandled,
618 events,
619 exception_handled_listeners_,
620 listener,
621 &have_exception_handled_listeners_);
Sebastien Hertzee1997a2013-09-19 14:47:09 +0200622 UpdateInterpreterHandlerTable();
jeffhao725a9572012-11-13 18:20:12 -0800623}
624
Nicolas Geoffray514a6162015-11-03 11:44:24 +0000625static void PotentiallyRemoveListenerFrom(Instrumentation::InstrumentationEvent event,
626 uint32_t events,
627 std::list<InstrumentationListener*>& list,
628 InstrumentationListener* listener,
629 bool* has_listener)
630 REQUIRES(Locks::mutator_lock_, !Locks::thread_list_lock_, !Locks::classlinker_classes_lock_) {
631 Locks::mutator_lock_->AssertExclusiveHeld(Thread::Current());
632 if (!HasEvent(event, events)) {
633 return;
634 }
635 auto it = std::find(list.begin(), list.end(), listener);
636 if (it != list.end()) {
637 // Just update the entry, do not remove from the list. Removing entries in the list
638 // is unsafe when mutators are iterating over it.
639 *it = nullptr;
640 }
641
642 // Check if the list contains any non-null listener, and update 'has_listener'.
643 for (InstrumentationListener* l : list) {
644 if (l != nullptr) {
David Srbecky28f6cff2018-10-16 15:07:28 +0100645 Runtime::DoAndMaybeSwitchInterpreter([=](){ *has_listener = true; });
Nicolas Geoffray514a6162015-11-03 11:44:24 +0000646 return;
647 }
648 }
David Srbecky28f6cff2018-10-16 15:07:28 +0100649 Runtime::DoAndMaybeSwitchInterpreter([=](){ *has_listener = false; });
Nicolas Geoffray514a6162015-11-03 11:44:24 +0000650}
651
Ian Rogers62d6c772013-02-27 08:32:07 -0800652void Instrumentation::RemoveListener(InstrumentationListener* listener, uint32_t events) {
653 Locks::mutator_lock_->AssertExclusiveHeld(Thread::Current());
Nicolas Geoffray514a6162015-11-03 11:44:24 +0000654 PotentiallyRemoveListenerFrom(kMethodEntered,
655 events,
656 method_entry_listeners_,
657 listener,
658 &have_method_entry_listeners_);
659 PotentiallyRemoveListenerFrom(kMethodExited,
660 events,
661 method_exit_listeners_,
662 listener,
663 &have_method_exit_listeners_);
664 PotentiallyRemoveListenerFrom(kMethodUnwind,
665 events,
666 method_unwind_listeners_,
667 listener,
668 &have_method_unwind_listeners_);
Nicolas Geoffray81f0f952016-01-20 16:25:19 +0000669 PotentiallyRemoveListenerFrom(kBranch,
Nicolas Geoffray514a6162015-11-03 11:44:24 +0000670 events,
Nicolas Geoffray81f0f952016-01-20 16:25:19 +0000671 branch_listeners_,
Nicolas Geoffray514a6162015-11-03 11:44:24 +0000672 listener,
Nicolas Geoffray81f0f952016-01-20 16:25:19 +0000673 &have_branch_listeners_);
Nicolas Geoffray514a6162015-11-03 11:44:24 +0000674 PotentiallyRemoveListenerFrom(kDexPcMoved,
675 events,
676 dex_pc_listeners_,
677 listener,
678 &have_dex_pc_listeners_);
679 PotentiallyRemoveListenerFrom(kFieldRead,
680 events,
681 field_read_listeners_,
682 listener,
683 &have_field_read_listeners_);
684 PotentiallyRemoveListenerFrom(kFieldWritten,
685 events,
686 field_write_listeners_,
687 listener,
688 &have_field_write_listeners_);
Alex Light6e1607e2017-08-23 10:06:18 -0700689 PotentiallyRemoveListenerFrom(kExceptionThrown,
Nicolas Geoffray514a6162015-11-03 11:44:24 +0000690 events,
Alex Light6e1607e2017-08-23 10:06:18 -0700691 exception_thrown_listeners_,
Nicolas Geoffray514a6162015-11-03 11:44:24 +0000692 listener,
Alex Light6e1607e2017-08-23 10:06:18 -0700693 &have_exception_thrown_listeners_);
Alex Lighte814f9d2017-07-31 16:14:39 -0700694 PotentiallyRemoveListenerFrom(kWatchedFramePop,
695 events,
696 watched_frame_pop_listeners_,
697 listener,
698 &have_watched_frame_pop_listeners_);
Alex Light9fb1ab12017-09-05 09:32:49 -0700699 PotentiallyRemoveListenerFrom(kExceptionHandled,
700 events,
701 exception_handled_listeners_,
702 listener,
703 &have_exception_handled_listeners_);
Sebastien Hertzee1997a2013-09-19 14:47:09 +0200704 UpdateInterpreterHandlerTable();
jeffhao725a9572012-11-13 18:20:12 -0800705}
706
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200707Instrumentation::InstrumentationLevel Instrumentation::GetCurrentInstrumentationLevel() const {
Alex Light4ba388a2017-01-27 10:26:49 -0800708 if (interpreter_stubs_installed_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200709 return InstrumentationLevel::kInstrumentWithInterpreter;
Ian Rogers62d6c772013-02-27 08:32:07 -0800710 } else if (entry_exit_stubs_installed_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200711 return InstrumentationLevel::kInstrumentWithInstrumentationStubs;
Ian Rogers62d6c772013-02-27 08:32:07 -0800712 } else {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200713 return InstrumentationLevel::kInstrumentNothing;
Ian Rogers62d6c772013-02-27 08:32:07 -0800714 }
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200715}
716
Alex Lightdba61482016-12-21 08:20:29 -0800717bool Instrumentation::RequiresInstrumentationInstallation(InstrumentationLevel new_level) const {
Alex Light4ba388a2017-01-27 10:26:49 -0800718 // We need to reinstall instrumentation if we go to a different level.
719 return GetCurrentInstrumentationLevel() != new_level;
Alex Lightdba61482016-12-21 08:20:29 -0800720}
721
Alex Light40607862019-05-06 18:16:24 +0000722void Instrumentation::UpdateInstrumentationLevels(InstrumentationLevel level) {
723 if (level == InstrumentationLevel::kInstrumentWithInterpreter) {
724 can_use_instrumentation_trampolines_ = false;
725 }
726 if (UNLIKELY(!can_use_instrumentation_trampolines_)) {
727 for (auto& p : requested_instrumentation_levels_) {
728 if (p.second == InstrumentationLevel::kInstrumentWithInstrumentationStubs) {
729 p.second = InstrumentationLevel::kInstrumentWithInterpreter;
730 }
731 }
732 }
733}
734
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200735void Instrumentation::ConfigureStubs(const char* key, InstrumentationLevel desired_level) {
736 // Store the instrumentation level for this key or remove it.
737 if (desired_level == InstrumentationLevel::kInstrumentNothing) {
738 // The client no longer needs instrumentation.
739 requested_instrumentation_levels_.erase(key);
740 } else {
741 // The client needs instrumentation.
742 requested_instrumentation_levels_.Overwrite(key, desired_level);
743 }
744
Alex Light40607862019-05-06 18:16:24 +0000745 UpdateInstrumentationLevels(desired_level);
746 UpdateStubs();
747}
748
749void Instrumentation::EnableSingleThreadDeopt() {
750 // Single-thread deopt only uses interpreter.
751 can_use_instrumentation_trampolines_ = false;
752 UpdateInstrumentationLevels(InstrumentationLevel::kInstrumentWithInterpreter);
753 UpdateStubs();
754}
755
756void Instrumentation::UpdateStubs() {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200757 // Look for the highest required instrumentation level.
758 InstrumentationLevel requested_level = InstrumentationLevel::kInstrumentNothing;
759 for (const auto& v : requested_instrumentation_levels_) {
760 requested_level = std::max(requested_level, v.second);
761 }
762
Alex Light40607862019-05-06 18:16:24 +0000763 DCHECK(can_use_instrumentation_trampolines_ ||
764 requested_level != InstrumentationLevel::kInstrumentWithInstrumentationStubs)
765 << "Use trampolines: " << can_use_instrumentation_trampolines_ << " level "
766 << requested_level;
767
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200768 interpret_only_ = (requested_level == InstrumentationLevel::kInstrumentWithInterpreter) ||
769 forced_interpret_only_;
770
Alex Lightdba61482016-12-21 08:20:29 -0800771 if (!RequiresInstrumentationInstallation(requested_level)) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800772 // We're already set.
773 return;
774 }
Sebastien Hertz7ec2f1c2014-03-27 20:06:47 +0100775 Thread* const self = Thread::Current();
Ian Rogers62d6c772013-02-27 08:32:07 -0800776 Runtime* runtime = Runtime::Current();
Sebastien Hertza8a697f2015-01-15 12:28:47 +0100777 Locks::mutator_lock_->AssertExclusiveHeld(self);
Ian Rogers62d6c772013-02-27 08:32:07 -0800778 Locks::thread_list_lock_->AssertNotHeld(self);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200779 if (requested_level > InstrumentationLevel::kInstrumentNothing) {
Alex Light4ba388a2017-01-27 10:26:49 -0800780 if (requested_level == InstrumentationLevel::kInstrumentWithInterpreter) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800781 interpreter_stubs_installed_ = true;
Ian Rogers62d6c772013-02-27 08:32:07 -0800782 entry_exit_stubs_installed_ = true;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200783 } else {
784 CHECK_EQ(requested_level, InstrumentationLevel::kInstrumentWithInstrumentationStubs);
785 entry_exit_stubs_installed_ = true;
786 interpreter_stubs_installed_ = false;
Ian Rogers62d6c772013-02-27 08:32:07 -0800787 }
Mathieu Chartiere0671ce2015-07-28 17:23:28 -0700788 InstallStubsClassVisitor visitor(this);
789 runtime->GetClassLinker()->VisitClasses(&visitor);
Ian Rogers62d6c772013-02-27 08:32:07 -0800790 instrumentation_stubs_installed_ = true;
Sebastien Hertz7ec2f1c2014-03-27 20:06:47 +0100791 MutexLock mu(self, *Locks::thread_list_lock_);
Ian Rogers62d6c772013-02-27 08:32:07 -0800792 runtime->GetThreadList()->ForEach(InstrumentationInstallStack, this);
793 } else {
794 interpreter_stubs_installed_ = false;
795 entry_exit_stubs_installed_ = false;
Mathieu Chartiere0671ce2015-07-28 17:23:28 -0700796 InstallStubsClassVisitor visitor(this);
797 runtime->GetClassLinker()->VisitClasses(&visitor);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100798 // Restore stack only if there is no method currently deoptimized.
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -0700799 bool empty;
800 {
Andreas Gampe7e56a072018-11-29 10:40:06 -0800801 ReaderMutexLock mu(self, *GetDeoptimizedMethodsLock());
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700802 empty = IsDeoptimizedMethodsEmpty(); // Avoid lock violation.
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -0700803 }
804 if (empty) {
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100805 MutexLock mu(self, *Locks::thread_list_lock_);
806 Runtime::Current()->GetThreadList()->ForEach(InstrumentationRestoreStack, this);
Nicolas Geoffray5a23d2e2015-11-03 18:58:57 +0000807 // Only do this after restoring, as walking the stack when restoring will see
808 // the instrumentation exit pc.
809 instrumentation_stubs_installed_ = false;
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100810 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800811 }
jeffhao725a9572012-11-13 18:20:12 -0800812}
813
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200814static void ResetQuickAllocEntryPointsForThread(Thread* thread, void* arg ATTRIBUTE_UNUSED) {
Mathieu Chartier5ace2012016-11-30 10:15:41 -0800815 thread->ResetQuickAllocEntryPointsForThread(kUseReadBarrier && thread->GetIsGcMarking());
Ian Rogersfa824272013-11-05 16:12:57 -0800816}
817
Mathieu Chartier9ef78b52014-09-25 17:03:12 -0700818void Instrumentation::SetEntrypointsInstrumented(bool instrumented) {
819 Thread* self = Thread::Current();
Mathieu Chartier661974a2014-01-09 11:23:53 -0800820 Runtime* runtime = Runtime::Current();
Mathieu Chartier9ef78b52014-09-25 17:03:12 -0700821 Locks::mutator_lock_->AssertNotHeld(self);
822 Locks::instrument_entrypoints_lock_->AssertHeld(self);
823 if (runtime->IsStarted()) {
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700824 ScopedSuspendAll ssa(__FUNCTION__);
Mathieu Chartier9ef78b52014-09-25 17:03:12 -0700825 MutexLock mu(self, *Locks::runtime_shutdown_lock_);
Mathieu Chartier661974a2014-01-09 11:23:53 -0800826 SetQuickAllocEntryPointsInstrumented(instrumented);
827 ResetQuickAllocEntryPoints();
Mathieu Chartier50e93312016-03-16 11:25:29 -0700828 alloc_entrypoints_instrumented_ = instrumented;
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700829 } else {
830 MutexLock mu(self, *Locks::runtime_shutdown_lock_);
831 SetQuickAllocEntryPointsInstrumented(instrumented);
Andreas Gampe157c77e2016-10-17 17:44:41 -0700832
833 // Note: ResetQuickAllocEntryPoints only works when the runtime is started. Manually run the
834 // update for just this thread.
Andreas Gampe162ae502016-10-18 10:03:42 -0700835 // Note: self may be null. One of those paths is setting instrumentation in the Heap
836 // constructor for gcstress mode.
837 if (self != nullptr) {
838 ResetQuickAllocEntryPointsForThread(self, nullptr);
839 }
Andreas Gampe157c77e2016-10-17 17:44:41 -0700840
Mathieu Chartier50e93312016-03-16 11:25:29 -0700841 alloc_entrypoints_instrumented_ = instrumented;
Mathieu Chartier661974a2014-01-09 11:23:53 -0800842 }
843}
844
Mathieu Chartier9ef78b52014-09-25 17:03:12 -0700845void Instrumentation::InstrumentQuickAllocEntryPoints() {
846 MutexLock mu(Thread::Current(), *Locks::instrument_entrypoints_lock_);
847 InstrumentQuickAllocEntryPointsLocked();
Ian Rogersfa824272013-11-05 16:12:57 -0800848}
849
Mathieu Chartier9ef78b52014-09-25 17:03:12 -0700850void Instrumentation::UninstrumentQuickAllocEntryPoints() {
851 MutexLock mu(Thread::Current(), *Locks::instrument_entrypoints_lock_);
852 UninstrumentQuickAllocEntryPointsLocked();
853}
854
855void Instrumentation::InstrumentQuickAllocEntryPointsLocked() {
856 Locks::instrument_entrypoints_lock_->AssertHeld(Thread::Current());
857 if (quick_alloc_entry_points_instrumentation_counter_ == 0) {
858 SetEntrypointsInstrumented(true);
Mathieu Chartiercbb2d202013-11-14 17:45:16 -0800859 }
Mathieu Chartier9ef78b52014-09-25 17:03:12 -0700860 ++quick_alloc_entry_points_instrumentation_counter_;
Mathieu Chartier9ef78b52014-09-25 17:03:12 -0700861}
862
863void Instrumentation::UninstrumentQuickAllocEntryPointsLocked() {
864 Locks::instrument_entrypoints_lock_->AssertHeld(Thread::Current());
865 CHECK_GT(quick_alloc_entry_points_instrumentation_counter_, 0U);
866 --quick_alloc_entry_points_instrumentation_counter_;
867 if (quick_alloc_entry_points_instrumentation_counter_ == 0) {
868 SetEntrypointsInstrumented(false);
869 }
Mathieu Chartiercbb2d202013-11-14 17:45:16 -0800870}
871
872void Instrumentation::ResetQuickAllocEntryPoints() {
873 Runtime* runtime = Runtime::Current();
874 if (runtime->IsStarted()) {
Mathieu Chartiere6da9af2013-12-16 11:54:42 -0800875 MutexLock mu(Thread::Current(), *Locks::thread_list_lock_);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700876 runtime->GetThreadList()->ForEach(ResetQuickAllocEntryPointsForThread, nullptr);
Ian Rogersfa824272013-11-05 16:12:57 -0800877 }
878}
879
Mingyao Yang3fd448a2016-05-10 14:30:41 -0700880void Instrumentation::UpdateMethodsCodeImpl(ArtMethod* method, const void* quick_code) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800881 const void* new_quick_code;
Ian Rogers62d6c772013-02-27 08:32:07 -0800882 if (LIKELY(!instrumentation_stubs_installed_)) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800883 new_quick_code = quick_code;
Jeff Hao65d15d92013-07-16 16:39:33 -0700884 } else {
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100885 if ((interpreter_stubs_installed_ || IsDeoptimized(method)) && !method->IsNative()) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800886 new_quick_code = GetQuickToInterpreterBridge();
Jeff Hao65d15d92013-07-16 16:39:33 -0700887 } else {
Mingyao Yang98d1cc82014-05-15 17:02:16 -0700888 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700889 if (class_linker->IsQuickResolutionStub(quick_code) ||
890 class_linker->IsQuickToInterpreterBridge(quick_code)) {
Mingyao Yang98d1cc82014-05-15 17:02:16 -0700891 new_quick_code = quick_code;
Alex Light6cae5ea2018-06-07 17:07:02 -0700892 } else if (entry_exit_stubs_installed_ &&
893 // We need to make sure not to replace anything that InstallStubsForMethod
894 // wouldn't. Specifically we cannot stub out Proxy.<init> since subtypes copy the
895 // implementation directly and this will confuse the instrumentation trampolines.
896 // TODO We should remove the need for this since it makes it impossible to profile
897 // Proxy.<init> correctly in all cases.
898 method != jni::DecodeArtMethod(WellKnownClasses::java_lang_reflect_Proxy_init)) {
Mingyao Yang98d1cc82014-05-15 17:02:16 -0700899 new_quick_code = GetQuickInstrumentationEntryPoint();
Alex Light2d441b12018-06-08 15:33:21 -0700900 if (!method->IsNative() && Runtime::Current()->GetJit() != nullptr) {
901 // Native methods use trampoline entrypoints during interpreter tracing.
Nicolas Geoffray226805d2018-12-14 10:59:02 +0000902 DCHECK(!Runtime::Current()->GetJit()->GetCodeCache()->GetGarbageCollectCodeUnsafe());
Alex Light2d441b12018-06-08 15:33:21 -0700903 ProfilingInfo* profiling_info = method->GetProfilingInfo(kRuntimePointerSize);
904 // Tracing will look at the saved entry point in the profiling info to know the actual
905 // entrypoint, so we store it here.
906 if (profiling_info != nullptr) {
907 profiling_info->SetSavedEntryPoint(quick_code);
908 }
909 }
Mingyao Yang98d1cc82014-05-15 17:02:16 -0700910 } else {
Mingyao Yang98d1cc82014-05-15 17:02:16 -0700911 new_quick_code = quick_code;
Mingyao Yang98d1cc82014-05-15 17:02:16 -0700912 }
Jeff Hao65d15d92013-07-16 16:39:33 -0700913 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800914 }
Elliott Hughes956af0f2014-12-11 14:34:28 -0800915 UpdateEntrypoints(method, new_quick_code);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100916}
917
Nicolas Geoffraya6e0e7d2018-01-26 13:16:50 +0000918void Instrumentation::UpdateNativeMethodsCodeToJitCode(ArtMethod* method, const void* quick_code) {
919 // We don't do any read barrier on `method`'s declaring class in this code, as the JIT might
920 // enter here on a soon-to-be deleted ArtMethod. Updating the entrypoint is OK though, as
921 // the ArtMethod is still in memory.
922 const void* new_quick_code = quick_code;
923 if (UNLIKELY(instrumentation_stubs_installed_) && entry_exit_stubs_installed_) {
924 new_quick_code = GetQuickInstrumentationEntryPoint();
925 }
926 UpdateEntrypoints(method, new_quick_code);
927}
928
Mingyao Yang3fd448a2016-05-10 14:30:41 -0700929void Instrumentation::UpdateMethodsCode(ArtMethod* method, const void* quick_code) {
930 DCHECK(method->GetDeclaringClass()->IsResolved());
931 UpdateMethodsCodeImpl(method, quick_code);
932}
933
Alex Light0a5ec3d2017-07-25 16:50:26 -0700934void Instrumentation::UpdateMethodsCodeToInterpreterEntryPoint(ArtMethod* method) {
935 UpdateMethodsCodeImpl(method, GetQuickToInterpreterBridge());
936}
937
Nicolas Geoffraya0619e22016-12-20 13:57:43 +0000938void Instrumentation::UpdateMethodsCodeForJavaDebuggable(ArtMethod* method,
939 const void* quick_code) {
940 // When the runtime is set to Java debuggable, we may update the entry points of
941 // all methods of a class to the interpreter bridge. A method's declaring class
942 // might not be in resolved state yet in that case, so we bypass the DCHECK in
943 // UpdateMethodsCode.
Mingyao Yang3fd448a2016-05-10 14:30:41 -0700944 UpdateMethodsCodeImpl(method, quick_code);
945}
946
Mathieu Chartiere401d142015-04-22 13:56:20 -0700947bool Instrumentation::AddDeoptimizedMethod(ArtMethod* method) {
948 if (IsDeoptimizedMethod(method)) {
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700949 // Already in the map. Return.
950 return false;
951 }
952 // Not found. Add it.
Mathieu Chartiere401d142015-04-22 13:56:20 -0700953 deoptimized_methods_.insert(method);
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700954 return true;
955}
956
Mathieu Chartiere401d142015-04-22 13:56:20 -0700957bool Instrumentation::IsDeoptimizedMethod(ArtMethod* method) {
958 return deoptimized_methods_.find(method) != deoptimized_methods_.end();
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700959}
960
Mathieu Chartiere401d142015-04-22 13:56:20 -0700961ArtMethod* Instrumentation::BeginDeoptimizedMethod() {
962 if (deoptimized_methods_.empty()) {
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700963 // Empty.
964 return nullptr;
965 }
Mathieu Chartiere401d142015-04-22 13:56:20 -0700966 return *deoptimized_methods_.begin();
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700967}
968
Mathieu Chartiere401d142015-04-22 13:56:20 -0700969bool Instrumentation::RemoveDeoptimizedMethod(ArtMethod* method) {
970 auto it = deoptimized_methods_.find(method);
971 if (it == deoptimized_methods_.end()) {
972 return false;
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700973 }
Mathieu Chartiere401d142015-04-22 13:56:20 -0700974 deoptimized_methods_.erase(it);
975 return true;
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700976}
977
978bool Instrumentation::IsDeoptimizedMethodsEmpty() const {
979 return deoptimized_methods_.empty();
980}
981
Mathieu Chartiere401d142015-04-22 13:56:20 -0700982void Instrumentation::Deoptimize(ArtMethod* method) {
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100983 CHECK(!method->IsNative());
984 CHECK(!method->IsProxyMethod());
Alex Light9139e002015-10-09 15:59:48 -0700985 CHECK(method->IsInvokable());
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100986
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -0700987 Thread* self = Thread::Current();
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -0700988 {
Andreas Gampe7e56a072018-11-29 10:40:06 -0800989 WriterMutexLock mu(self, *GetDeoptimizedMethodsLock());
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -0700990 bool has_not_been_deoptimized = AddDeoptimizedMethod(method);
David Sehr709b0702016-10-13 09:12:37 -0700991 CHECK(has_not_been_deoptimized) << "Method " << ArtMethod::PrettyMethod(method)
Daniel Mihalyica1d06c2014-08-18 18:45:31 +0200992 << " is already deoptimized";
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -0700993 }
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100994 if (!interpreter_stubs_installed_) {
Elliott Hughes956af0f2014-12-11 14:34:28 -0800995 UpdateEntrypoints(method, GetQuickInstrumentationEntryPoint());
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100996
997 // Install instrumentation exit stub and instrumentation frames. We may already have installed
998 // these previously so it will only cover the newly created frames.
999 instrumentation_stubs_installed_ = true;
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -07001000 MutexLock mu(self, *Locks::thread_list_lock_);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001001 Runtime::Current()->GetThreadList()->ForEach(InstrumentationInstallStack, this);
1002 }
1003}
1004
Mathieu Chartiere401d142015-04-22 13:56:20 -07001005void Instrumentation::Undeoptimize(ArtMethod* method) {
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001006 CHECK(!method->IsNative());
1007 CHECK(!method->IsProxyMethod());
Alex Light9139e002015-10-09 15:59:48 -07001008 CHECK(method->IsInvokable());
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001009
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -07001010 Thread* self = Thread::Current();
1011 bool empty;
1012 {
Andreas Gampe7e56a072018-11-29 10:40:06 -08001013 WriterMutexLock mu(self, *GetDeoptimizedMethodsLock());
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -07001014 bool found_and_erased = RemoveDeoptimizedMethod(method);
David Sehr709b0702016-10-13 09:12:37 -07001015 CHECK(found_and_erased) << "Method " << ArtMethod::PrettyMethod(method)
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -07001016 << " is not deoptimized";
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -07001017 empty = IsDeoptimizedMethodsEmpty();
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -07001018 }
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001019
1020 // Restore code and possibly stack only if we did not deoptimize everything.
1021 if (!interpreter_stubs_installed_) {
1022 // Restore its code or resolution trampoline.
1023 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Ian Rogersef7d42f2014-01-06 12:55:46 -08001024 if (method->IsStatic() && !method->IsConstructor() &&
1025 !method->GetDeclaringClass()->IsInitialized()) {
Elliott Hughes956af0f2014-12-11 14:34:28 -08001026 UpdateEntrypoints(method, GetQuickResolutionStub());
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001027 } else {
Nicolas Geoffraya0619e22016-12-20 13:57:43 +00001028 const void* quick_code = NeedDebugVersionFor(method)
1029 ? GetQuickToInterpreterBridge()
Alex Lightfc49fec2018-01-16 22:28:36 +00001030 : class_linker->GetQuickOatCodeFor(method);
Elliott Hughes956af0f2014-12-11 14:34:28 -08001031 UpdateEntrypoints(method, quick_code);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001032 }
1033
1034 // If there is no deoptimized method left, we can restore the stack of each thread.
Alex Lightf244a572018-06-08 13:56:51 -07001035 if (empty && !entry_exit_stubs_installed_) {
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -07001036 MutexLock mu(self, *Locks::thread_list_lock_);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001037 Runtime::Current()->GetThreadList()->ForEach(InstrumentationRestoreStack, this);
1038 instrumentation_stubs_installed_ = false;
1039 }
1040 }
1041}
1042
Mathieu Chartiere401d142015-04-22 13:56:20 -07001043bool Instrumentation::IsDeoptimized(ArtMethod* method) {
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001044 DCHECK(method != nullptr);
Andreas Gampe7e56a072018-11-29 10:40:06 -08001045 ReaderMutexLock mu(Thread::Current(), *GetDeoptimizedMethodsLock());
Mathieu Chartiere401d142015-04-22 13:56:20 -07001046 return IsDeoptimizedMethod(method);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001047}
1048
1049void Instrumentation::EnableDeoptimization() {
Andreas Gampe7e56a072018-11-29 10:40:06 -08001050 ReaderMutexLock mu(Thread::Current(), *GetDeoptimizedMethodsLock());
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -07001051 CHECK(IsDeoptimizedMethodsEmpty());
Sebastien Hertz11d40c22014-02-19 18:00:17 +01001052 CHECK_EQ(deoptimization_enabled_, false);
1053 deoptimization_enabled_ = true;
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001054}
1055
Sebastien Hertz0462c4c2015-04-01 16:34:17 +02001056void Instrumentation::DisableDeoptimization(const char* key) {
Sebastien Hertz11d40c22014-02-19 18:00:17 +01001057 CHECK_EQ(deoptimization_enabled_, true);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001058 // If we deoptimized everything, undo it.
Alex Lightdba61482016-12-21 08:20:29 -08001059 InstrumentationLevel level = GetCurrentInstrumentationLevel();
1060 if (level == InstrumentationLevel::kInstrumentWithInterpreter) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +02001061 UndeoptimizeEverything(key);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001062 }
1063 // Undeoptimized selected methods.
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -07001064 while (true) {
Mathieu Chartiere401d142015-04-22 13:56:20 -07001065 ArtMethod* method;
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -07001066 {
Andreas Gampe7e56a072018-11-29 10:40:06 -08001067 ReaderMutexLock mu(Thread::Current(), *GetDeoptimizedMethodsLock());
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -07001068 if (IsDeoptimizedMethodsEmpty()) {
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -07001069 break;
1070 }
Hiroshi Yamauchi799eb3a2014-07-18 15:38:17 -07001071 method = BeginDeoptimizedMethod();
1072 CHECK(method != nullptr);
Mathieu Chartier3b05e9b2014-03-25 09:29:43 -07001073 }
1074 Undeoptimize(method);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001075 }
Sebastien Hertz11d40c22014-02-19 18:00:17 +01001076 deoptimization_enabled_ = false;
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001077}
1078
Sebastien Hertz11d40c22014-02-19 18:00:17 +01001079// Indicates if instrumentation should notify method enter/exit events to the listeners.
1080bool Instrumentation::ShouldNotifyMethodEnterExitEvents() const {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +02001081 if (!HasMethodEntryListeners() && !HasMethodExitListeners()) {
1082 return false;
1083 }
Sebastien Hertz7ec2f1c2014-03-27 20:06:47 +01001084 return !deoptimization_enabled_ && !interpreter_stubs_installed_;
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001085}
1086
Sebastien Hertz0462c4c2015-04-01 16:34:17 +02001087void Instrumentation::DeoptimizeEverything(const char* key) {
1088 CHECK(deoptimization_enabled_);
1089 ConfigureStubs(key, InstrumentationLevel::kInstrumentWithInterpreter);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001090}
1091
Sebastien Hertz0462c4c2015-04-01 16:34:17 +02001092void Instrumentation::UndeoptimizeEverything(const char* key) {
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001093 CHECK(interpreter_stubs_installed_);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +02001094 CHECK(deoptimization_enabled_);
1095 ConfigureStubs(key, InstrumentationLevel::kInstrumentNothing);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001096}
1097
Sebastien Hertz0462c4c2015-04-01 16:34:17 +02001098void Instrumentation::EnableMethodTracing(const char* key, bool needs_interpreter) {
1099 InstrumentationLevel level;
1100 if (needs_interpreter) {
1101 level = InstrumentationLevel::kInstrumentWithInterpreter;
1102 } else {
1103 level = InstrumentationLevel::kInstrumentWithInstrumentationStubs;
1104 }
1105 ConfigureStubs(key, level);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001106}
1107
Sebastien Hertz0462c4c2015-04-01 16:34:17 +02001108void Instrumentation::DisableMethodTracing(const char* key) {
1109 ConfigureStubs(key, InstrumentationLevel::kInstrumentNothing);
jeffhao725a9572012-11-13 18:20:12 -08001110}
1111
Alex Light2d441b12018-06-08 15:33:21 -07001112const void* Instrumentation::GetCodeForInvoke(ArtMethod* method) const {
1113 // This is called by instrumentation entry only and that should never be getting proxy methods.
1114 DCHECK(!method->IsProxyMethod()) << method->PrettyMethod();
1115 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1116 if (LIKELY(!instrumentation_stubs_installed_ && !interpreter_stubs_installed_)) {
1117 // In general we just return whatever the method thinks its entrypoint is here. The only
1118 // exception is if it still has the instrumentation entrypoint. That means we are racing another
1119 // thread getting rid of instrumentation which is unexpected but possible. In that case we want
1120 // to wait and try to get it from the oat file or jit.
1121 const void* code = method->GetEntryPointFromQuickCompiledCodePtrSize(kRuntimePointerSize);
1122 DCHECK(code != nullptr);
1123 if (code != GetQuickInstrumentationEntryPoint()) {
1124 return code;
1125 } else if (method->IsNative()) {
1126 return class_linker->GetQuickOatCodeFor(method);
1127 }
1128 // We don't know what it is. Fallthough to try to find the code from the JIT or Oat file.
1129 } else if (method->IsNative()) {
1130 // TODO We could have JIT compiled native entrypoints. It might be worth it to find these.
1131 return class_linker->GetQuickOatCodeFor(method);
1132 } else if (UNLIKELY(interpreter_stubs_installed_)) {
1133 return GetQuickToInterpreterBridge();
1134 }
1135 // Since the method cannot be native due to ifs above we can always fall back to interpreter
1136 // bridge.
1137 const void* result = GetQuickToInterpreterBridge();
1138 if (!NeedDebugVersionFor(method)) {
1139 // If we don't need a debug version we should see what the oat file/class linker has to say.
1140 result = class_linker->GetQuickOatCodeFor(method);
1141 }
1142 // If both those fail try the jit.
1143 if (result == GetQuickToInterpreterBridge()) {
1144 jit::Jit* jit = Runtime::Current()->GetJit();
1145 if (jit != nullptr) {
1146 const void* res = jit->GetCodeCache()->FindCompiledCodeForInstrumentation(method);
1147 if (res != nullptr) {
1148 result = res;
1149 }
1150 }
1151 }
1152 return result;
1153}
1154
Andreas Gampe542451c2016-07-26 09:02:02 -07001155const void* Instrumentation::GetQuickCodeFor(ArtMethod* method, PointerSize pointer_size) const {
Vladimir Marko97d7e1c2016-10-04 14:44:28 +01001156 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Ian Rogers62d6c772013-02-27 08:32:07 -08001157 if (LIKELY(!instrumentation_stubs_installed_)) {
Mathieu Chartiera7dd0382014-11-20 17:08:58 -08001158 const void* code = method->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
Vladimir Marko8a630572014-04-09 18:45:35 +01001159 DCHECK(code != nullptr);
Ian Rogers6f3dbba2014-10-14 17:41:57 -07001160 if (LIKELY(!class_linker->IsQuickResolutionStub(code) &&
1161 !class_linker->IsQuickToInterpreterBridge(code)) &&
1162 !class_linker->IsQuickResolutionStub(code) &&
1163 !class_linker->IsQuickToInterpreterBridge(code)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001164 return code;
1165 }
1166 }
Alex Lightfc49fec2018-01-16 22:28:36 +00001167 return class_linker->GetQuickOatCodeFor(method);
jeffhao725a9572012-11-13 18:20:12 -08001168}
1169
Alex Lightd7661582017-05-01 13:48:16 -07001170void Instrumentation::MethodEnterEventImpl(Thread* thread,
1171 ObjPtr<mirror::Object> this_object,
Mathieu Chartiere401d142015-04-22 13:56:20 -07001172 ArtMethod* method,
Ian Rogers62d6c772013-02-27 08:32:07 -08001173 uint32_t dex_pc) const {
Mingyao Yang2ee17902017-08-30 11:37:08 -07001174 DCHECK(!method->IsRuntimeMethod());
Nicolas Geoffray514a6162015-11-03 11:44:24 +00001175 if (HasMethodEntryListeners()) {
Alex Lightd7661582017-05-01 13:48:16 -07001176 Thread* self = Thread::Current();
1177 StackHandleScope<1> hs(self);
1178 Handle<mirror::Object> thiz(hs.NewHandle(this_object));
Nicolas Geoffray514a6162015-11-03 11:44:24 +00001179 for (InstrumentationListener* listener : method_entry_listeners_) {
1180 if (listener != nullptr) {
Alex Lightd7661582017-05-01 13:48:16 -07001181 listener->MethodEntered(thread, thiz, method, dex_pc);
Nicolas Geoffray514a6162015-11-03 11:44:24 +00001182 }
1183 }
Ian Rogers62d6c772013-02-27 08:32:07 -08001184 }
1185}
1186
Alex Lightb7c640d2019-03-20 15:52:13 -07001187template <>
Alex Lightd7661582017-05-01 13:48:16 -07001188void Instrumentation::MethodExitEventImpl(Thread* thread,
1189 ObjPtr<mirror::Object> this_object,
Mathieu Chartiere401d142015-04-22 13:56:20 -07001190 ArtMethod* method,
Alex Lightd7661582017-05-01 13:48:16 -07001191 uint32_t dex_pc,
Alex Lightb7c640d2019-03-20 15:52:13 -07001192 OptionalFrame frame,
1193 MutableHandle<mirror::Object>& return_value) const {
1194 if (HasMethodExitListeners()) {
1195 Thread* self = Thread::Current();
1196 StackHandleScope<1> hs(self);
1197 Handle<mirror::Object> thiz(hs.NewHandle(this_object));
1198 for (InstrumentationListener* listener : method_exit_listeners_) {
1199 if (listener != nullptr) {
1200 listener->MethodExited(thread, thiz, method, dex_pc, frame, return_value);
1201 }
1202 }
1203 }
1204}
1205
1206template<> void Instrumentation::MethodExitEventImpl(Thread* thread,
1207 ObjPtr<mirror::Object> this_object,
1208 ArtMethod* method,
1209 uint32_t dex_pc,
1210 OptionalFrame frame,
1211 JValue& return_value) const {
Nicolas Geoffray514a6162015-11-03 11:44:24 +00001212 if (HasMethodExitListeners()) {
Alex Lightd7661582017-05-01 13:48:16 -07001213 Thread* self = Thread::Current();
1214 StackHandleScope<2> hs(self);
1215 Handle<mirror::Object> thiz(hs.NewHandle(this_object));
Alex Lightb7c640d2019-03-20 15:52:13 -07001216 if (method->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetReturnTypePrimitive() !=
1217 Primitive::kPrimNot) {
Alex Lightd7661582017-05-01 13:48:16 -07001218 for (InstrumentationListener* listener : method_exit_listeners_) {
1219 if (listener != nullptr) {
Alex Lightb7c640d2019-03-20 15:52:13 -07001220 listener->MethodExited(thread, thiz, method, dex_pc, frame, return_value);
Alex Lightd7661582017-05-01 13:48:16 -07001221 }
1222 }
1223 } else {
Alex Lightb7c640d2019-03-20 15:52:13 -07001224 MutableHandle<mirror::Object> ret(hs.NewHandle(return_value.GetL()));
1225 MethodExitEventImpl(thread, thiz.Get(), method, dex_pc, frame, ret);
1226 return_value.SetL(ret.Get());
Nicolas Geoffray514a6162015-11-03 11:44:24 +00001227 }
Ian Rogers62d6c772013-02-27 08:32:07 -08001228 }
1229}
1230
Alex Lightd7661582017-05-01 13:48:16 -07001231void Instrumentation::MethodUnwindEvent(Thread* thread,
Vladimir Marko19711d42019-04-12 14:05:34 +01001232 ObjPtr<mirror::Object> this_object,
Mathieu Chartiere401d142015-04-22 13:56:20 -07001233 ArtMethod* method,
Ian Rogers62d6c772013-02-27 08:32:07 -08001234 uint32_t dex_pc) const {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +02001235 if (HasMethodUnwindListeners()) {
Alex Lightd7661582017-05-01 13:48:16 -07001236 Thread* self = Thread::Current();
1237 StackHandleScope<1> hs(self);
1238 Handle<mirror::Object> thiz(hs.NewHandle(this_object));
Mathieu Chartier02e25112013-08-14 16:14:24 -07001239 for (InstrumentationListener* listener : method_unwind_listeners_) {
Nicolas Geoffray514a6162015-11-03 11:44:24 +00001240 if (listener != nullptr) {
Alex Lightd7661582017-05-01 13:48:16 -07001241 listener->MethodUnwind(thread, thiz, method, dex_pc);
Nicolas Geoffray514a6162015-11-03 11:44:24 +00001242 }
Ian Rogers62d6c772013-02-27 08:32:07 -08001243 }
1244 }
1245}
1246
Alex Lightd7661582017-05-01 13:48:16 -07001247void Instrumentation::DexPcMovedEventImpl(Thread* thread,
1248 ObjPtr<mirror::Object> this_object,
Mathieu Chartiere401d142015-04-22 13:56:20 -07001249 ArtMethod* method,
Ian Rogers62d6c772013-02-27 08:32:07 -08001250 uint32_t dex_pc) const {
Alex Lightd7661582017-05-01 13:48:16 -07001251 Thread* self = Thread::Current();
1252 StackHandleScope<1> hs(self);
1253 Handle<mirror::Object> thiz(hs.NewHandle(this_object));
Nicolas Geoffray514a6162015-11-03 11:44:24 +00001254 for (InstrumentationListener* listener : dex_pc_listeners_) {
1255 if (listener != nullptr) {
Alex Lightd7661582017-05-01 13:48:16 -07001256 listener->DexPcMoved(thread, thiz, method, dex_pc);
Nicolas Geoffray514a6162015-11-03 11:44:24 +00001257 }
Ian Rogers62d6c772013-02-27 08:32:07 -08001258 }
1259}
1260
Nicolas Geoffray81f0f952016-01-20 16:25:19 +00001261void Instrumentation::BranchImpl(Thread* thread,
1262 ArtMethod* method,
1263 uint32_t dex_pc,
1264 int32_t offset) const {
1265 for (InstrumentationListener* listener : branch_listeners_) {
Nicolas Geoffray514a6162015-11-03 11:44:24 +00001266 if (listener != nullptr) {
Nicolas Geoffray81f0f952016-01-20 16:25:19 +00001267 listener->Branch(thread, method, dex_pc, offset);
Nicolas Geoffray514a6162015-11-03 11:44:24 +00001268 }
Mathieu Chartiere5f13e52015-02-24 09:37:21 -08001269 }
1270}
1271
Alex Lighte814f9d2017-07-31 16:14:39 -07001272void Instrumentation::WatchedFramePopImpl(Thread* thread, const ShadowFrame& frame) const {
1273 for (InstrumentationListener* listener : watched_frame_pop_listeners_) {
1274 if (listener != nullptr) {
1275 listener->WatchedFramePop(thread, frame);
1276 }
1277 }
1278}
1279
Alex Lightd7661582017-05-01 13:48:16 -07001280void Instrumentation::FieldReadEventImpl(Thread* thread,
1281 ObjPtr<mirror::Object> this_object,
1282 ArtMethod* method,
1283 uint32_t dex_pc,
Mathieu Chartierc7853442015-03-27 14:35:38 -07001284 ArtField* field) const {
Alex Lightd7661582017-05-01 13:48:16 -07001285 Thread* self = Thread::Current();
1286 StackHandleScope<1> hs(self);
1287 Handle<mirror::Object> thiz(hs.NewHandle(this_object));
Nicolas Geoffray514a6162015-11-03 11:44:24 +00001288 for (InstrumentationListener* listener : field_read_listeners_) {
1289 if (listener != nullptr) {
Alex Lightd7661582017-05-01 13:48:16 -07001290 listener->FieldRead(thread, thiz, method, dex_pc, field);
Nicolas Geoffray514a6162015-11-03 11:44:24 +00001291 }
Sebastien Hertz3f52eaf2014-04-04 17:50:18 +02001292 }
1293}
1294
Alex Lightd7661582017-05-01 13:48:16 -07001295void Instrumentation::FieldWriteEventImpl(Thread* thread,
1296 ObjPtr<mirror::Object> this_object,
1297 ArtMethod* method,
1298 uint32_t dex_pc,
1299 ArtField* field,
1300 const JValue& field_value) const {
1301 Thread* self = Thread::Current();
1302 StackHandleScope<2> hs(self);
1303 Handle<mirror::Object> thiz(hs.NewHandle(this_object));
1304 if (field->IsPrimitiveType()) {
1305 for (InstrumentationListener* listener : field_write_listeners_) {
1306 if (listener != nullptr) {
1307 listener->FieldWritten(thread, thiz, method, dex_pc, field, field_value);
1308 }
1309 }
1310 } else {
1311 Handle<mirror::Object> val(hs.NewHandle(field_value.GetL()));
1312 for (InstrumentationListener* listener : field_write_listeners_) {
1313 if (listener != nullptr) {
1314 listener->FieldWritten(thread, thiz, method, dex_pc, field, val);
1315 }
Nicolas Geoffray514a6162015-11-03 11:44:24 +00001316 }
Sebastien Hertz3f52eaf2014-04-04 17:50:18 +02001317 }
1318}
1319
Alex Light6e1607e2017-08-23 10:06:18 -07001320void Instrumentation::ExceptionThrownEvent(Thread* thread,
Vladimir Marko19711d42019-04-12 14:05:34 +01001321 ObjPtr<mirror::Throwable> exception_object) const {
Hiroshi Yamauchi3481f7a2017-02-10 12:07:36 -08001322 Thread* self = Thread::Current();
1323 StackHandleScope<1> hs(self);
1324 Handle<mirror::Throwable> h_exception(hs.NewHandle(exception_object));
Alex Light6e1607e2017-08-23 10:06:18 -07001325 if (HasExceptionThrownListeners()) {
Hiroshi Yamauchi3481f7a2017-02-10 12:07:36 -08001326 DCHECK_EQ(thread->GetException(), h_exception.Get());
Jeff Haoc0bd4da2013-04-11 15:52:28 -07001327 thread->ClearException();
Alex Light6e1607e2017-08-23 10:06:18 -07001328 for (InstrumentationListener* listener : exception_thrown_listeners_) {
Nicolas Geoffray514a6162015-11-03 11:44:24 +00001329 if (listener != nullptr) {
Alex Light6e1607e2017-08-23 10:06:18 -07001330 listener->ExceptionThrown(thread, h_exception);
Nicolas Geoffray514a6162015-11-03 11:44:24 +00001331 }
Ian Rogers62d6c772013-02-27 08:32:07 -08001332 }
Alex Light9fb1ab12017-09-05 09:32:49 -07001333 // See b/65049545 for discussion about this behavior.
1334 thread->AssertNoPendingException();
Hiroshi Yamauchi3481f7a2017-02-10 12:07:36 -08001335 thread->SetException(h_exception.Get());
Ian Rogers62d6c772013-02-27 08:32:07 -08001336 }
1337}
1338
Alex Light9fb1ab12017-09-05 09:32:49 -07001339void Instrumentation::ExceptionHandledEvent(Thread* thread,
Vladimir Marko19711d42019-04-12 14:05:34 +01001340 ObjPtr<mirror::Throwable> exception_object) const {
Alex Light9fb1ab12017-09-05 09:32:49 -07001341 Thread* self = Thread::Current();
1342 StackHandleScope<1> hs(self);
1343 Handle<mirror::Throwable> h_exception(hs.NewHandle(exception_object));
1344 if (HasExceptionHandledListeners()) {
1345 // We should have cleared the exception so that callers can detect a new one.
1346 DCHECK(thread->GetException() == nullptr);
1347 for (InstrumentationListener* listener : exception_handled_listeners_) {
1348 if (listener != nullptr) {
1349 listener->ExceptionHandled(thread, h_exception);
1350 }
1351 }
1352 }
1353}
1354
Sebastien Hertzb2feaaf2015-10-12 13:40:10 +00001355// Computes a frame ID by ignoring inlined frames.
1356size_t Instrumentation::ComputeFrameId(Thread* self,
1357 size_t frame_depth,
1358 size_t inlined_frames_before_frame) {
1359 CHECK_GE(frame_depth, inlined_frames_before_frame);
1360 size_t no_inline_depth = frame_depth - inlined_frames_before_frame;
1361 return StackVisitor::ComputeNumFrames(self, kInstrumentationStackWalk) - no_inline_depth;
1362}
1363
Ian Rogers62d6c772013-02-27 08:32:07 -08001364static void CheckStackDepth(Thread* self, const InstrumentationStackFrame& instrumentation_frame,
1365 int delta)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001366 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray8e5bd182015-05-06 11:34:34 +01001367 size_t frame_id = StackVisitor::ComputeNumFrames(self, kInstrumentationStackWalk) + delta;
Ian Rogers62d6c772013-02-27 08:32:07 -08001368 if (frame_id != instrumentation_frame.frame_id_) {
1369 LOG(ERROR) << "Expected frame_id=" << frame_id << " but found "
1370 << instrumentation_frame.frame_id_;
1371 StackVisitor::DescribeStack(self);
1372 CHECK_EQ(frame_id, instrumentation_frame.frame_id_);
1373 }
1374}
1375
Vladimir Marko19711d42019-04-12 14:05:34 +01001376void Instrumentation::PushInstrumentationStackFrame(Thread* self,
1377 ObjPtr<mirror::Object> this_object,
Mathieu Chartiere401d142015-04-22 13:56:20 -07001378 ArtMethod* method,
Vladimir Marko19711d42019-04-12 14:05:34 +01001379 uintptr_t lr,
1380 bool interpreter_entry) {
Alex Lightb7edcda2017-04-27 13:20:31 -07001381 DCHECK(!self->IsExceptionPending());
Ian Rogers62d6c772013-02-27 08:32:07 -08001382 std::deque<instrumentation::InstrumentationStackFrame>* stack = self->GetInstrumentationStack();
1383 if (kVerboseInstrumentation) {
David Sehr709b0702016-10-13 09:12:37 -07001384 LOG(INFO) << "Entering " << ArtMethod::PrettyMethod(method) << " from PC "
1385 << reinterpret_cast<void*>(lr);
Ian Rogers62d6c772013-02-27 08:32:07 -08001386 }
Alex Lightb7edcda2017-04-27 13:20:31 -07001387
1388 // We send the enter event before pushing the instrumentation frame to make cleanup easier. If the
1389 // event causes an exception we can simply send the unwind event and return.
1390 StackHandleScope<1> hs(self);
1391 Handle<mirror::Object> h_this(hs.NewHandle(this_object));
1392 if (!interpreter_entry) {
1393 MethodEnterEvent(self, h_this.Get(), method, 0);
1394 if (self->IsExceptionPending()) {
1395 MethodUnwindEvent(self, h_this.Get(), method, 0);
1396 return;
1397 }
1398 }
1399
1400 // We have a callee-save frame meaning this value is guaranteed to never be 0.
1401 DCHECK(!self->IsExceptionPending());
1402 size_t frame_id = StackVisitor::ComputeNumFrames(self, kInstrumentationStackWalk);
1403
1404 instrumentation::InstrumentationStackFrame instrumentation_frame(h_this.Get(), method, lr,
Jeff Hao9a916d32013-06-27 18:45:37 -07001405 frame_id, interpreter_entry);
Ian Rogers62d6c772013-02-27 08:32:07 -08001406 stack->push_front(instrumentation_frame);
Ian Rogers62d6c772013-02-27 08:32:07 -08001407}
1408
Mingyao Yang2ee17902017-08-30 11:37:08 -07001409DeoptimizationMethodType Instrumentation::GetDeoptimizationMethodType(ArtMethod* method) {
1410 if (method->IsRuntimeMethod()) {
1411 // Certain methods have strict requirement on whether the dex instruction
1412 // should be re-executed upon deoptimization.
1413 if (method == Runtime::Current()->GetCalleeSaveMethod(
1414 CalleeSaveType::kSaveEverythingForClinit)) {
1415 return DeoptimizationMethodType::kKeepDexPc;
1416 }
1417 if (method == Runtime::Current()->GetCalleeSaveMethod(
1418 CalleeSaveType::kSaveEverythingForSuspendCheck)) {
1419 return DeoptimizationMethodType::kKeepDexPc;
1420 }
1421 }
1422 return DeoptimizationMethodType::kDefault;
1423}
1424
1425// Try to get the shorty of a runtime method if it's an invocation stub.
Andreas Gampec7d878d2018-11-19 18:42:06 +00001426static char GetRuntimeMethodShorty(Thread* thread) REQUIRES_SHARED(Locks::mutator_lock_) {
1427 char shorty = 'V';
1428 StackVisitor::WalkStack(
1429 [&shorty](const art::StackVisitor* stack_visitor) REQUIRES_SHARED(Locks::mutator_lock_) {
1430 ArtMethod* m = stack_visitor->GetMethod();
1431 if (m == nullptr || m->IsRuntimeMethod()) {
1432 return true;
Andreas Gampe3d477f32018-11-16 16:40:45 +00001433 }
Andreas Gampec7d878d2018-11-19 18:42:06 +00001434 // The first Java method.
1435 if (m->IsNative()) {
1436 // Use JNI method's shorty for the jni stub.
1437 shorty = m->GetShorty()[0];
1438 } else if (m->IsProxyMethod()) {
1439 // Proxy method just invokes its proxied method via
1440 // art_quick_proxy_invoke_handler.
1441 shorty = m->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetShorty()[0];
1442 } else {
1443 const Instruction& instr = m->DexInstructions().InstructionAt(stack_visitor->GetDexPc());
1444 if (instr.IsInvoke()) {
1445 auto get_method_index_fn = [](ArtMethod* caller,
1446 const Instruction& inst,
1447 uint32_t dex_pc)
1448 REQUIRES_SHARED(Locks::mutator_lock_) {
1449 switch (inst.Opcode()) {
1450 case Instruction::INVOKE_VIRTUAL_RANGE_QUICK:
1451 case Instruction::INVOKE_VIRTUAL_QUICK: {
1452 uint16_t method_idx = caller->GetIndexFromQuickening(dex_pc);
1453 CHECK_NE(method_idx, DexFile::kDexNoIndex16);
1454 return method_idx;
1455 }
1456 default: {
1457 return static_cast<uint16_t>(inst.VRegB());
1458 }
1459 }
1460 };
Nicolas Geoffrayec43a012018-11-17 13:10:40 +00001461
Andreas Gampec7d878d2018-11-19 18:42:06 +00001462 uint16_t method_index = get_method_index_fn(m, instr, stack_visitor->GetDexPc());
1463 const DexFile* dex_file = m->GetDexFile();
1464 if (interpreter::IsStringInit(dex_file, method_index)) {
1465 // Invoking string init constructor is turned into invoking
1466 // StringFactory.newStringFromChars() which returns a string.
1467 shorty = 'L';
1468 } else {
1469 shorty = dex_file->GetMethodShorty(method_index)[0];
1470 }
1471
1472 } else {
1473 // It could be that a non-invoke opcode invokes a stub, which in turn
1474 // invokes Java code. In such cases, we should never expect a return
1475 // value from the stub.
1476 }
1477 }
1478 // Stop stack walking since we've seen a Java frame.
1479 return false;
1480 },
1481 thread,
1482 /* context= */ nullptr,
1483 art::StackVisitor::StackWalkKind::kIncludeInlinedFrames);
1484 return shorty;
1485}
Mingyao Yang2ee17902017-08-30 11:37:08 -07001486
Alex Lightb7edcda2017-04-27 13:20:31 -07001487TwoWordReturn Instrumentation::PopInstrumentationStackFrame(Thread* self,
1488 uintptr_t* return_pc,
1489 uint64_t* gpr_result,
1490 uint64_t* fpr_result) {
1491 DCHECK(gpr_result != nullptr);
1492 DCHECK(fpr_result != nullptr);
Ian Rogers62d6c772013-02-27 08:32:07 -08001493 // Do the pop.
1494 std::deque<instrumentation::InstrumentationStackFrame>* stack = self->GetInstrumentationStack();
1495 CHECK_GT(stack->size(), 0U);
1496 InstrumentationStackFrame instrumentation_frame = stack->front();
1497 stack->pop_front();
1498
1499 // Set return PC and check the sanity of the stack.
1500 *return_pc = instrumentation_frame.return_pc_;
1501 CheckStackDepth(self, instrumentation_frame, 0);
Ian Rogers1d8cdbc2014-09-22 22:51:09 -07001502 self->VerifyStack();
Ian Rogers62d6c772013-02-27 08:32:07 -08001503
Mathieu Chartiere401d142015-04-22 13:56:20 -07001504 ArtMethod* method = instrumentation_frame.method_;
Mathieu Chartierbfd9a432014-05-21 17:43:44 -07001505 uint32_t length;
Andreas Gampe542451c2016-07-26 09:02:02 -07001506 const PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
Mingyao Yang2ee17902017-08-30 11:37:08 -07001507 char return_shorty;
1508
1509 // Runtime method does not call into MethodExitEvent() so there should not be
1510 // suspension point below.
1511 ScopedAssertNoThreadSuspension ants(__FUNCTION__, method->IsRuntimeMethod());
1512 if (method->IsRuntimeMethod()) {
1513 if (method != Runtime::Current()->GetCalleeSaveMethod(
1514 CalleeSaveType::kSaveEverythingForClinit)) {
1515 // If the caller is at an invocation point and the runtime method is not
1516 // for clinit, we need to pass return results to the caller.
1517 // We need the correct shorty to decide whether we need to pass the return
1518 // result for deoptimization below.
Andreas Gampec7d878d2018-11-19 18:42:06 +00001519 return_shorty = GetRuntimeMethodShorty(self);
Mingyao Yang2ee17902017-08-30 11:37:08 -07001520 } else {
1521 // Some runtime methods such as allocations, unresolved field getters, etc.
1522 // have return value. We don't need to set return_value since MethodExitEvent()
1523 // below isn't called for runtime methods. Deoptimization doesn't need the
1524 // value either since the dex instruction will be re-executed by the
1525 // interpreter, except these two cases:
1526 // (1) For an invoke, which is handled above to get the correct shorty.
1527 // (2) For MONITOR_ENTER/EXIT, which cannot be re-executed since it's not
1528 // idempotent. However there is no return value for it anyway.
1529 return_shorty = 'V';
1530 }
1531 } else {
1532 return_shorty = method->GetInterfaceMethodIfProxy(pointer_size)->GetShorty(&length)[0];
1533 }
1534
Alex Lightb7edcda2017-04-27 13:20:31 -07001535 bool is_ref = return_shorty == '[' || return_shorty == 'L';
1536 StackHandleScope<1> hs(self);
1537 MutableHandle<mirror::Object> res(hs.NewHandle<mirror::Object>(nullptr));
Ian Rogers62d6c772013-02-27 08:32:07 -08001538 JValue return_value;
1539 if (return_shorty == 'V') {
1540 return_value.SetJ(0);
1541 } else if (return_shorty == 'F' || return_shorty == 'D') {
Alex Lightb7edcda2017-04-27 13:20:31 -07001542 return_value.SetJ(*fpr_result);
Ian Rogers62d6c772013-02-27 08:32:07 -08001543 } else {
Alex Lightb7edcda2017-04-27 13:20:31 -07001544 return_value.SetJ(*gpr_result);
1545 }
1546 if (is_ref) {
1547 // Take a handle to the return value so we won't lose it if we suspend.
1548 res.Assign(return_value.GetL());
Ian Rogers62d6c772013-02-27 08:32:07 -08001549 }
1550 // TODO: improve the dex pc information here, requires knowledge of current PC as opposed to
1551 // return_pc.
Andreas Gampee2abbc62017-09-15 11:59:26 -07001552 uint32_t dex_pc = dex::kDexNoIndex;
Mingyao Yang2ee17902017-08-30 11:37:08 -07001553 if (!method->IsRuntimeMethod() && !instrumentation_frame.interpreter_entry_) {
Vladimir Marko19711d42019-04-12 14:05:34 +01001554 ObjPtr<mirror::Object> this_object = instrumentation_frame.this_object_;
Alex Lightb7c640d2019-03-20 15:52:13 -07001555 MethodExitEvent(
1556 self, this_object, instrumentation_frame.method_, dex_pc, OptionalFrame{}, return_value);
Sebastien Hertz320deb22014-06-11 19:45:05 +02001557 }
jeffhao725a9572012-11-13 18:20:12 -08001558
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001559 // Deoptimize if the caller needs to continue execution in the interpreter. Do nothing if we get
1560 // back to an upcall.
1561 NthCallerVisitor visitor(self, 1, true);
1562 visitor.WalkStack(true);
Sebastien Hertz270a0e12015-01-16 19:49:09 +01001563 bool deoptimize = (visitor.caller != nullptr) &&
Daniel Mihalyieb076692014-08-22 17:33:31 +02001564 (interpreter_stubs_installed_ || IsDeoptimized(visitor.caller) ||
Alex Light3dacdd62019-03-12 15:45:47 +00001565 self->IsForceInterpreter() ||
Daniel Mihalyieb076692014-08-22 17:33:31 +02001566 Dbg::IsForcedInterpreterNeededForUpcall(self, visitor.caller));
Alex Lightb7edcda2017-04-27 13:20:31 -07001567 if (is_ref) {
1568 // Restore the return value if it's a reference since it might have moved.
1569 *reinterpret_cast<mirror::Object**>(gpr_result) = res.Get();
1570 }
Nicolas Geoffraya0619e22016-12-20 13:57:43 +00001571 if (deoptimize && Runtime::Current()->IsAsyncDeoptimizeable(*return_pc)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001572 if (kVerboseInstrumentation) {
Andreas Gampe46ee31b2016-12-14 10:11:49 -08001573 LOG(INFO) << "Deoptimizing "
1574 << visitor.caller->PrettyMethod()
1575 << " by returning from "
1576 << method->PrettyMethod()
1577 << " with result "
1578 << std::hex << return_value.GetJ() << std::dec
1579 << " in "
1580 << *self;
Ian Rogers62d6c772013-02-27 08:32:07 -08001581 }
Mingyao Yang2ee17902017-08-30 11:37:08 -07001582 DeoptimizationMethodType deopt_method_type = GetDeoptimizationMethodType(method);
Nicolas Geoffray73be1e82015-09-17 15:22:56 +01001583 self->PushDeoptimizationContext(return_value,
Mingyao Yang2ee17902017-08-30 11:37:08 -07001584 return_shorty == 'L' || return_shorty == '[',
Andreas Gampe98ea9d92018-10-19 14:06:15 -07001585 /* exception= */ nullptr ,
1586 /* from_code= */ false,
Mingyao Yang2ee17902017-08-30 11:37:08 -07001587 deopt_method_type);
Andreas Gamped58342c2014-06-05 14:18:08 -07001588 return GetTwoWordSuccessValue(*return_pc,
1589 reinterpret_cast<uintptr_t>(GetQuickDeoptimizationEntryPoint()));
Ian Rogers62d6c772013-02-27 08:32:07 -08001590 } else {
Nicolas Geoffraya0619e22016-12-20 13:57:43 +00001591 if (deoptimize && !Runtime::Current()->IsAsyncDeoptimizeable(*return_pc)) {
Alex Lightd8eb6732018-01-29 15:16:02 -08001592 VLOG(deopt) << "Got a deoptimization request on un-deoptimizable " << method->PrettyMethod()
1593 << " at PC " << reinterpret_cast<void*>(*return_pc);
Nicolas Geoffraya0619e22016-12-20 13:57:43 +00001594 }
Ian Rogers62d6c772013-02-27 08:32:07 -08001595 if (kVerboseInstrumentation) {
David Sehr709b0702016-10-13 09:12:37 -07001596 LOG(INFO) << "Returning from " << method->PrettyMethod()
Brian Carlstrom2d888622013-07-18 17:02:00 -07001597 << " to PC " << reinterpret_cast<void*>(*return_pc);
Ian Rogers62d6c772013-02-27 08:32:07 -08001598 }
Andreas Gamped58342c2014-06-05 14:18:08 -07001599 return GetTwoWordSuccessValue(0, *return_pc);
Ian Rogers62d6c772013-02-27 08:32:07 -08001600 }
jeffhao725a9572012-11-13 18:20:12 -08001601}
1602
Alex Light2c8206f2018-06-08 14:51:09 -07001603uintptr_t Instrumentation::PopFramesForDeoptimization(Thread* self, size_t nframes) const {
Ian Rogers62d6c772013-02-27 08:32:07 -08001604 std::deque<instrumentation::InstrumentationStackFrame>* stack = self->GetInstrumentationStack();
Alex Light2c8206f2018-06-08 14:51:09 -07001605 CHECK_GE(stack->size(), nframes);
1606 if (nframes == 0) {
1607 return 0u;
1608 }
1609 // Only need to send instrumentation events if it's not for deopt (do give the log messages if we
1610 // have verbose-instrumentation anyway though).
1611 if (kVerboseInstrumentation) {
1612 for (size_t i = 0; i < nframes; i++) {
1613 LOG(INFO) << "Popping for deoptimization " << stack->at(i).method_->PrettyMethod();
Mingyao Yang2ee17902017-08-30 11:37:08 -07001614 }
Ian Rogers62d6c772013-02-27 08:32:07 -08001615 }
Alex Light2c8206f2018-06-08 14:51:09 -07001616 // Now that we've sent all the instrumentation events we can actually modify the
1617 // instrumentation-stack. We cannot do this earlier since MethodUnwindEvent can re-enter java and
1618 // do other things that require the instrumentation stack to be in a consistent state with the
1619 // actual stack.
1620 for (size_t i = 0; i < nframes - 1; i++) {
1621 stack->pop_front();
1622 }
1623 uintptr_t return_pc = stack->front().return_pc_;
Alex Lightb7edcda2017-04-27 13:20:31 -07001624 stack->pop_front();
Alex Light2c8206f2018-06-08 14:51:09 -07001625 return return_pc;
Ian Rogers62d6c772013-02-27 08:32:07 -08001626}
1627
1628std::string InstrumentationStackFrame::Dump() const {
1629 std::ostringstream os;
David Sehr709b0702016-10-13 09:12:37 -07001630 os << "Frame " << frame_id_ << " " << ArtMethod::PrettyMethod(method_) << ":"
Ian Rogers62d6c772013-02-27 08:32:07 -08001631 << reinterpret_cast<void*>(return_pc_) << " this=" << reinterpret_cast<void*>(this_object_);
1632 return os.str();
1633}
1634
1635} // namespace instrumentation
jeffhao725a9572012-11-13 18:20:12 -08001636} // namespace art