blob: 90bc1222206fa0053c2096de47b3700481ba1749 [file] [log] [blame]
Andreas Gampe77708d92016-10-07 11:48:21 -07001/* Copyright (C) 2016 The Android Open Source Project
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This file implements interfaces from the file jvmti.h. This implementation
5 * is licensed under the same terms as the file jvmti.h. The
6 * copyright and license information for the file jvmti.h follows.
7 *
8 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
9 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10 *
11 * This code is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License version 2 only, as
13 * published by the Free Software Foundation. Oracle designates this
14 * particular file as subject to the "Classpath" exception as provided
15 * by Oracle in the LICENSE file that accompanied this code.
16 *
17 * This code is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * version 2 for more details (a copy is included in the LICENSE file that
21 * accompanied this code).
22 *
23 * You should have received a copy of the GNU General Public License version
24 * 2 along with this work; if not, write to the Free Software Foundation,
25 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26 *
27 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
28 * or visit www.oracle.com if you need additional information or have any
29 * questions.
30 */
31
Andreas Gampe27fa96c2016-10-07 15:05:24 -070032#include "events-inl.h"
Andreas Gampe77708d92016-10-07 11:48:21 -070033
34#include "art_jvmti.h"
Alex Lightb7edcda2017-04-27 13:20:31 -070035#include "art_method-inl.h"
Andreas Gampe27fa96c2016-10-07 15:05:24 -070036#include "base/logging.h"
37#include "gc/allocation_listener.h"
Andreas Gampe9b8c5882016-10-21 15:27:46 -070038#include "gc/gc_pause_listener.h"
39#include "gc/heap.h"
Alex Lightb7edcda2017-04-27 13:20:31 -070040#include "gc/scoped_gc_critical_section.h"
Andreas Gampec15a2f42017-04-21 12:09:39 -070041#include "handle_scope-inl.h"
Andreas Gampe27fa96c2016-10-07 15:05:24 -070042#include "instrumentation.h"
43#include "jni_env_ext-inl.h"
Alex Lightb7edcda2017-04-27 13:20:31 -070044#include "jni_internal.h"
Andreas Gampe27fa96c2016-10-07 15:05:24 -070045#include "mirror/class.h"
Andreas Gampec15a2f42017-04-21 12:09:39 -070046#include "mirror/object-inl.h"
Andreas Gampe27fa96c2016-10-07 15:05:24 -070047#include "runtime.h"
48#include "ScopedLocalRef.h"
Andreas Gampec02685c2016-10-17 17:40:27 -070049#include "scoped_thread_state_change-inl.h"
Alex Lightb7edcda2017-04-27 13:20:31 -070050#include "thread-inl.h"
51#include "thread_list.h"
52#include "ti_phase.h"
Andreas Gampe77708d92016-10-07 11:48:21 -070053
54namespace openjdkjvmti {
55
Alex Light73afd322017-01-18 11:17:47 -080056bool EventMasks::IsEnabledAnywhere(ArtJvmtiEvent event) {
57 return global_event_mask.Test(event) || unioned_thread_event_mask.Test(event);
58}
59
Andreas Gampe77708d92016-10-07 11:48:21 -070060EventMask& EventMasks::GetEventMask(art::Thread* thread) {
61 if (thread == nullptr) {
62 return global_event_mask;
63 }
64
65 for (auto& pair : thread_event_masks) {
66 const UniqueThread& unique_thread = pair.first;
67 if (unique_thread.first == thread &&
68 unique_thread.second == static_cast<uint32_t>(thread->GetTid())) {
69 return pair.second;
70 }
71 }
72
73 // TODO: Remove old UniqueThread with the same pointer, if exists.
74
75 thread_event_masks.emplace_back(UniqueThread(thread, thread->GetTid()), EventMask());
76 return thread_event_masks.back().second;
77}
78
79EventMask* EventMasks::GetEventMaskOrNull(art::Thread* thread) {
80 if (thread == nullptr) {
81 return &global_event_mask;
82 }
83
84 for (auto& pair : thread_event_masks) {
85 const UniqueThread& unique_thread = pair.first;
86 if (unique_thread.first == thread &&
87 unique_thread.second == static_cast<uint32_t>(thread->GetTid())) {
88 return &pair.second;
89 }
90 }
91
92 return nullptr;
93}
94
95
Alex Light40d87f42017-01-18 10:27:06 -080096void EventMasks::EnableEvent(art::Thread* thread, ArtJvmtiEvent event) {
Andreas Gampe77708d92016-10-07 11:48:21 -070097 DCHECK(EventMask::EventIsInRange(event));
98 GetEventMask(thread).Set(event);
99 if (thread != nullptr) {
100 unioned_thread_event_mask.Set(event, true);
101 }
102}
103
Alex Light40d87f42017-01-18 10:27:06 -0800104void EventMasks::DisableEvent(art::Thread* thread, ArtJvmtiEvent event) {
Andreas Gampe77708d92016-10-07 11:48:21 -0700105 DCHECK(EventMask::EventIsInRange(event));
106 GetEventMask(thread).Set(event, false);
107 if (thread != nullptr) {
108 // Regenerate union for the event.
109 bool union_value = false;
110 for (auto& pair : thread_event_masks) {
111 union_value |= pair.second.Test(event);
112 if (union_value) {
113 break;
114 }
115 }
116 unioned_thread_event_mask.Set(event, union_value);
117 }
118}
119
Alex Light73afd322017-01-18 11:17:47 -0800120void EventMasks::HandleChangedCapabilities(const jvmtiCapabilities& caps, bool caps_added) {
121 if (UNLIKELY(caps.can_retransform_classes == 1)) {
122 // If we are giving this env the retransform classes cap we need to switch all events of
123 // NonTransformable to Transformable and vice versa.
124 ArtJvmtiEvent to_remove = caps_added ? ArtJvmtiEvent::kClassFileLoadHookNonRetransformable
125 : ArtJvmtiEvent::kClassFileLoadHookRetransformable;
126 ArtJvmtiEvent to_add = caps_added ? ArtJvmtiEvent::kClassFileLoadHookRetransformable
127 : ArtJvmtiEvent::kClassFileLoadHookNonRetransformable;
128 if (global_event_mask.Test(to_remove)) {
129 CHECK(!global_event_mask.Test(to_add));
130 global_event_mask.Set(to_remove, false);
131 global_event_mask.Set(to_add, true);
132 }
133
134 if (unioned_thread_event_mask.Test(to_remove)) {
135 CHECK(!unioned_thread_event_mask.Test(to_add));
136 unioned_thread_event_mask.Set(to_remove, false);
137 unioned_thread_event_mask.Set(to_add, true);
138 }
139 for (auto thread_mask : thread_event_masks) {
140 if (thread_mask.second.Test(to_remove)) {
141 CHECK(!thread_mask.second.Test(to_add));
142 thread_mask.second.Set(to_remove, false);
143 thread_mask.second.Set(to_add, true);
144 }
145 }
146 }
147}
148
Andreas Gampe77708d92016-10-07 11:48:21 -0700149void EventHandler::RegisterArtJvmTiEnv(ArtJvmTiEnv* env) {
Alex Lightbb766462017-04-12 16:13:33 -0700150 // Since we never shrink this array we might as well try to fill gaps.
151 auto it = std::find(envs.begin(), envs.end(), nullptr);
152 if (it != envs.end()) {
153 *it = env;
154 } else {
155 envs.push_back(env);
156 }
Andreas Gampe77708d92016-10-07 11:48:21 -0700157}
158
Andreas Gampe3a7eb142017-01-19 21:59:22 -0800159void EventHandler::RemoveArtJvmTiEnv(ArtJvmTiEnv* env) {
Alex Lightbb766462017-04-12 16:13:33 -0700160 // Since we might be currently iterating over the envs list we cannot actually erase elements.
161 // Instead we will simply replace them with 'nullptr' and skip them manually.
Andreas Gampe3a7eb142017-01-19 21:59:22 -0800162 auto it = std::find(envs.begin(), envs.end(), env);
163 if (it != envs.end()) {
Alex Lightbb766462017-04-12 16:13:33 -0700164 *it = nullptr;
Andreas Gampe3a7eb142017-01-19 21:59:22 -0800165 for (size_t i = static_cast<size_t>(ArtJvmtiEvent::kMinEventTypeVal);
166 i <= static_cast<size_t>(ArtJvmtiEvent::kMaxEventTypeVal);
167 ++i) {
168 RecalculateGlobalEventMask(static_cast<ArtJvmtiEvent>(i));
169 }
170 }
171}
172
Alex Light40d87f42017-01-18 10:27:06 -0800173static bool IsThreadControllable(ArtJvmtiEvent event) {
Andreas Gampe77708d92016-10-07 11:48:21 -0700174 switch (event) {
Alex Light40d87f42017-01-18 10:27:06 -0800175 case ArtJvmtiEvent::kVmInit:
176 case ArtJvmtiEvent::kVmStart:
177 case ArtJvmtiEvent::kVmDeath:
178 case ArtJvmtiEvent::kThreadStart:
179 case ArtJvmtiEvent::kCompiledMethodLoad:
180 case ArtJvmtiEvent::kCompiledMethodUnload:
181 case ArtJvmtiEvent::kDynamicCodeGenerated:
182 case ArtJvmtiEvent::kDataDumpRequest:
Andreas Gampe77708d92016-10-07 11:48:21 -0700183 return false;
184
185 default:
186 return true;
187 }
188}
189
Andreas Gampe27fa96c2016-10-07 15:05:24 -0700190class JvmtiAllocationListener : public art::gc::AllocationListener {
191 public:
192 explicit JvmtiAllocationListener(EventHandler* handler) : handler_(handler) {}
193
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700194 void ObjectAllocated(art::Thread* self, art::ObjPtr<art::mirror::Object>* obj, size_t byte_count)
Andreas Gampe9b8c5882016-10-21 15:27:46 -0700195 OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) {
Andreas Gampe27fa96c2016-10-07 15:05:24 -0700196 DCHECK_EQ(self, art::Thread::Current());
197
Alex Light40d87f42017-01-18 10:27:06 -0800198 if (handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kVmObjectAlloc)) {
Mathieu Chartiera7118042016-10-12 15:45:58 -0700199 art::StackHandleScope<1> hs(self);
200 auto h = hs.NewHandleWrapper(obj);
Andreas Gampe27fa96c2016-10-07 15:05:24 -0700201 // jvmtiEventVMObjectAlloc parameters:
202 // jvmtiEnv *jvmti_env,
203 // JNIEnv* jni_env,
204 // jthread thread,
205 // jobject object,
206 // jclass object_klass,
207 // jlong size
208 art::JNIEnvExt* jni_env = self->GetJniEnv();
209
210 jthread thread_peer;
211 if (self->IsStillStarting()) {
212 thread_peer = nullptr;
213 } else {
214 thread_peer = jni_env->AddLocalReference<jthread>(self->GetPeer());
215 }
216
217 ScopedLocalRef<jthread> thread(jni_env, thread_peer);
218 ScopedLocalRef<jobject> object(
219 jni_env, jni_env->AddLocalReference<jobject>(*obj));
220 ScopedLocalRef<jclass> klass(
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700221 jni_env, jni_env->AddLocalReference<jclass>(obj->Ptr()->GetClass()));
Andreas Gampe27fa96c2016-10-07 15:05:24 -0700222
Andreas Gampe983c1752017-01-23 19:46:56 -0800223 handler_->DispatchEvent<ArtJvmtiEvent::kVmObjectAlloc>(self,
224 reinterpret_cast<JNIEnv*>(jni_env),
225 thread.get(),
226 object.get(),
227 klass.get(),
228 static_cast<jlong>(byte_count));
Andreas Gampe27fa96c2016-10-07 15:05:24 -0700229 }
230 }
231
232 private:
233 EventHandler* handler_;
234};
235
236static void SetupObjectAllocationTracking(art::gc::AllocationListener* listener, bool enable) {
Andreas Gampec02685c2016-10-17 17:40:27 -0700237 // We must not hold the mutator lock here, but if we're in FastJNI, for example, we might. For
238 // now, do a workaround: (possibly) acquire and release.
239 art::ScopedObjectAccess soa(art::Thread::Current());
240 art::ScopedThreadSuspension sts(soa.Self(), art::ThreadState::kSuspended);
Andreas Gampe27fa96c2016-10-07 15:05:24 -0700241 if (enable) {
242 art::Runtime::Current()->GetHeap()->SetAllocationListener(listener);
243 } else {
244 art::Runtime::Current()->GetHeap()->RemoveAllocationListener();
245 }
246}
247
Andreas Gampe9b8c5882016-10-21 15:27:46 -0700248// Report GC pauses (see spec) as GARBAGE_COLLECTION_START and GARBAGE_COLLECTION_END.
249class JvmtiGcPauseListener : public art::gc::GcPauseListener {
250 public:
251 explicit JvmtiGcPauseListener(EventHandler* handler)
252 : handler_(handler),
253 start_enabled_(false),
254 finish_enabled_(false) {}
255
256 void StartPause() OVERRIDE {
Andreas Gampe983c1752017-01-23 19:46:56 -0800257 handler_->DispatchEvent<ArtJvmtiEvent::kGarbageCollectionStart>(nullptr);
Andreas Gampe9b8c5882016-10-21 15:27:46 -0700258 }
259
260 void EndPause() OVERRIDE {
Andreas Gampe983c1752017-01-23 19:46:56 -0800261 handler_->DispatchEvent<ArtJvmtiEvent::kGarbageCollectionFinish>(nullptr);
Andreas Gampe9b8c5882016-10-21 15:27:46 -0700262 }
263
264 bool IsEnabled() {
265 return start_enabled_ || finish_enabled_;
266 }
267
268 void SetStartEnabled(bool e) {
269 start_enabled_ = e;
270 }
271
272 void SetFinishEnabled(bool e) {
273 finish_enabled_ = e;
274 }
275
276 private:
277 EventHandler* handler_;
278 bool start_enabled_;
279 bool finish_enabled_;
280};
281
Alex Light40d87f42017-01-18 10:27:06 -0800282static void SetupGcPauseTracking(JvmtiGcPauseListener* listener, ArtJvmtiEvent event, bool enable) {
Andreas Gampe9b8c5882016-10-21 15:27:46 -0700283 bool old_state = listener->IsEnabled();
284
Alex Light40d87f42017-01-18 10:27:06 -0800285 if (event == ArtJvmtiEvent::kGarbageCollectionStart) {
Andreas Gampe9b8c5882016-10-21 15:27:46 -0700286 listener->SetStartEnabled(enable);
287 } else {
288 listener->SetFinishEnabled(enable);
289 }
290
291 bool new_state = listener->IsEnabled();
292
293 if (old_state != new_state) {
294 if (new_state) {
295 art::Runtime::Current()->GetHeap()->SetGcPauseListener(listener);
296 } else {
297 art::Runtime::Current()->GetHeap()->RemoveGcPauseListener();
298 }
299 }
300}
301
Alex Lightb7edcda2017-04-27 13:20:31 -0700302template<typename Type>
303static Type AddLocalRef(art::JNIEnvExt* e, art::mirror::Object* obj)
304 REQUIRES_SHARED(art::Locks::mutator_lock_) {
305 return (obj == nullptr) ? nullptr : e->AddLocalReference<Type>(obj);
306}
307
308class JvmtiMethodTraceListener FINAL : public art::instrumentation::InstrumentationListener {
309 public:
310 explicit JvmtiMethodTraceListener(EventHandler* handler) : event_handler_(handler) {}
311
312 template<ArtJvmtiEvent kEvent, typename ...Args>
313 void RunEventCallback(art::Thread* self, art::JNIEnvExt* jnienv, Args... args)
314 REQUIRES_SHARED(art::Locks::mutator_lock_) {
315 ScopedLocalRef<jthread> thread_jni(jnienv, AddLocalRef<jthread>(jnienv, self->GetPeer()));
316 // Just give the event a good sized JNI frame. 100 should be fine.
317 jnienv->PushFrame(100);
318 {
319 // Need to do trampoline! :(
320 art::ScopedThreadSuspension sts(self, art::ThreadState::kNative);
321 event_handler_->DispatchEvent<kEvent>(self,
322 static_cast<JNIEnv*>(jnienv),
323 thread_jni.get(),
324 args...);
325 }
326 jnienv->PopFrame();
327 }
328
329 // Call-back for when a method is entered.
330 void MethodEntered(art::Thread* self,
331 art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
332 art::ArtMethod* method,
333 uint32_t dex_pc ATTRIBUTE_UNUSED)
334 REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE {
335 if (!method->IsRuntimeMethod() &&
336 event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kMethodEntry)) {
337 art::JNIEnvExt* jnienv = self->GetJniEnv();
338 RunEventCallback<ArtJvmtiEvent::kMethodEntry>(self,
339 jnienv,
340 art::jni::EncodeArtMethod(method));
341 }
342 }
343
344 // Callback for when a method is exited with a reference return value.
345 void MethodExited(art::Thread* self,
346 art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
347 art::ArtMethod* method,
348 uint32_t dex_pc ATTRIBUTE_UNUSED,
349 art::Handle<art::mirror::Object> return_value)
350 REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE {
351 if (!method->IsRuntimeMethod() &&
352 event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kMethodExit)) {
353 DCHECK_EQ(method->GetReturnTypePrimitive(), art::Primitive::kPrimNot)
354 << method->PrettyMethod();
355 DCHECK(!self->IsExceptionPending());
356 jvalue val;
357 art::JNIEnvExt* jnienv = self->GetJniEnv();
358 ScopedLocalRef<jobject> return_jobj(jnienv, AddLocalRef<jobject>(jnienv, return_value.Get()));
359 val.l = return_jobj.get();
360 RunEventCallback<ArtJvmtiEvent::kMethodExit>(
361 self,
362 jnienv,
363 art::jni::EncodeArtMethod(method),
364 /*was_popped_by_exception*/ static_cast<jboolean>(JNI_FALSE),
365 val);
366 }
367 }
368
369 // Call-back for when a method is exited.
370 void MethodExited(art::Thread* self,
371 art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
372 art::ArtMethod* method,
373 uint32_t dex_pc ATTRIBUTE_UNUSED,
374 const art::JValue& return_value)
375 REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE {
376 if (!method->IsRuntimeMethod() &&
377 event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kMethodExit)) {
378 DCHECK_NE(method->GetReturnTypePrimitive(), art::Primitive::kPrimNot)
379 << method->PrettyMethod();
380 DCHECK(!self->IsExceptionPending());
381 jvalue val;
382 art::JNIEnvExt* jnienv = self->GetJniEnv();
383 // 64bit integer is the largest value in the union so we should be fine simply copying it into
384 // the union.
385 val.j = return_value.GetJ();
386 RunEventCallback<ArtJvmtiEvent::kMethodExit>(
387 self,
388 jnienv,
389 art::jni::EncodeArtMethod(method),
390 /*was_popped_by_exception*/ static_cast<jboolean>(JNI_FALSE),
391 val);
392 }
393 }
394
395 // Call-back for when a method is popped due to an exception throw. A method will either cause a
396 // MethodExited call-back or a MethodUnwind call-back when its activation is removed.
397 void MethodUnwind(art::Thread* self,
398 art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
399 art::ArtMethod* method,
400 uint32_t dex_pc ATTRIBUTE_UNUSED)
401 REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE {
402 if (!method->IsRuntimeMethod() &&
403 event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kMethodExit)) {
404 jvalue val;
405 // Just set this to 0xffffffffffffffff so it's not uninitialized.
406 val.j = static_cast<jlong>(-1);
407 art::JNIEnvExt* jnienv = self->GetJniEnv();
408 art::StackHandleScope<1> hs(self);
409 art::Handle<art::mirror::Throwable> old_exception(hs.NewHandle(self->GetException()));
410 CHECK(!old_exception.IsNull());
411 self->ClearException();
412 RunEventCallback<ArtJvmtiEvent::kMethodExit>(
413 self,
414 jnienv,
415 art::jni::EncodeArtMethod(method),
416 /*was_popped_by_exception*/ static_cast<jboolean>(JNI_TRUE),
417 val);
418 // Match RI behavior of just throwing away original exception if a new one is thrown.
419 if (LIKELY(!self->IsExceptionPending())) {
420 self->SetException(old_exception.Get());
421 }
422 }
423 }
424
425 // Call-back for when the dex pc moves in a method. We don't currently have any events associated
426 // with this.
427 void DexPcMoved(art::Thread* self ATTRIBUTE_UNUSED,
428 art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
429 art::ArtMethod* method ATTRIBUTE_UNUSED,
430 uint32_t new_dex_pc ATTRIBUTE_UNUSED)
431 REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE {
432 return;
433 }
434
435 // Call-back for when we read from a field.
436 void FieldRead(art::Thread* self ATTRIBUTE_UNUSED,
437 art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
438 art::ArtMethod* method ATTRIBUTE_UNUSED,
439 uint32_t dex_pc ATTRIBUTE_UNUSED,
440 art::ArtField* field ATTRIBUTE_UNUSED)
441 REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE {
442 return;
443 }
444
445 // Call-back for when we write into a field.
446 void FieldWritten(art::Thread* self ATTRIBUTE_UNUSED,
447 art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
448 art::ArtMethod* method ATTRIBUTE_UNUSED,
449 uint32_t dex_pc ATTRIBUTE_UNUSED,
450 art::ArtField* field ATTRIBUTE_UNUSED,
451 const art::JValue& field_value ATTRIBUTE_UNUSED)
452 REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE {
453 return;
454 }
455
456 // Call-back when an exception is caught.
457 void ExceptionCaught(art::Thread* self ATTRIBUTE_UNUSED,
458 art::Handle<art::mirror::Throwable> exception_object ATTRIBUTE_UNUSED)
459 REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE {
460 return;
461 }
462
463 // Call-back for when we execute a branch.
464 void Branch(art::Thread* self ATTRIBUTE_UNUSED,
465 art::ArtMethod* method ATTRIBUTE_UNUSED,
466 uint32_t dex_pc ATTRIBUTE_UNUSED,
467 int32_t dex_pc_offset ATTRIBUTE_UNUSED)
468 REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE {
469 return;
470 }
471
472 // Call-back for when we get an invokevirtual or an invokeinterface.
473 void InvokeVirtualOrInterface(art::Thread* self ATTRIBUTE_UNUSED,
474 art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
475 art::ArtMethod* caller ATTRIBUTE_UNUSED,
476 uint32_t dex_pc ATTRIBUTE_UNUSED,
477 art::ArtMethod* callee ATTRIBUTE_UNUSED)
478 REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE {
479 return;
480 }
481
482 private:
483 EventHandler* const event_handler_;
484};
485
486static uint32_t GetInstrumentationEventsFor(ArtJvmtiEvent event) {
487 switch (event) {
488 case ArtJvmtiEvent::kMethodEntry:
489 return art::instrumentation::Instrumentation::kMethodEntered;
490 case ArtJvmtiEvent::kMethodExit:
491 return art::instrumentation::Instrumentation::kMethodExited |
492 art::instrumentation::Instrumentation::kMethodUnwind;
493 default:
494 LOG(FATAL) << "Unknown event ";
495 return 0;
496 }
497}
498
499static void SetupMethodTraceListener(JvmtiMethodTraceListener* listener,
500 ArtJvmtiEvent event,
501 bool enable) {
502 uint32_t new_events = GetInstrumentationEventsFor(event);
503 art::instrumentation::Instrumentation* instr = art::Runtime::Current()->GetInstrumentation();
504 art::gc::ScopedGCCriticalSection gcs(art::Thread::Current(),
505 art::gc::kGcCauseInstrumentation,
506 art::gc::kCollectorTypeInstrumentation);
507 art::ScopedSuspendAll ssa("jvmti method tracing installation");
508 if (enable) {
509 if (!instr->AreAllMethodsDeoptimized()) {
510 instr->EnableMethodTracing("jvmti-tracing", /*needs_interpreter*/true);
511 }
512 instr->AddListener(listener, new_events);
513 } else {
514 instr->RemoveListener(listener, new_events);
515 }
516}
517
Andreas Gampe77708d92016-10-07 11:48:21 -0700518// Handle special work for the given event type, if necessary.
Alex Light40d87f42017-01-18 10:27:06 -0800519void EventHandler::HandleEventType(ArtJvmtiEvent event, bool enable) {
Andreas Gampe9b8c5882016-10-21 15:27:46 -0700520 switch (event) {
Alex Light40d87f42017-01-18 10:27:06 -0800521 case ArtJvmtiEvent::kVmObjectAlloc:
Andreas Gampe9b8c5882016-10-21 15:27:46 -0700522 SetupObjectAllocationTracking(alloc_listener_.get(), enable);
523 return;
524
Alex Light40d87f42017-01-18 10:27:06 -0800525 case ArtJvmtiEvent::kGarbageCollectionStart:
526 case ArtJvmtiEvent::kGarbageCollectionFinish:
Andreas Gampe9b8c5882016-10-21 15:27:46 -0700527 SetupGcPauseTracking(gc_pause_listener_.get(), event, enable);
528 return;
529
Alex Lightb7edcda2017-04-27 13:20:31 -0700530 case ArtJvmtiEvent::kMethodEntry:
531 case ArtJvmtiEvent::kMethodExit:
532 SetupMethodTraceListener(method_trace_listener_.get(), event, enable);
533 return;
534
Andreas Gampe9b8c5882016-10-21 15:27:46 -0700535 default:
536 break;
Andreas Gampe27fa96c2016-10-07 15:05:24 -0700537 }
Andreas Gampe77708d92016-10-07 11:48:21 -0700538}
539
Alex Light9db679d2017-01-25 15:28:04 -0800540// Checks to see if the env has the capabilities associated with the given event.
541static bool HasAssociatedCapability(ArtJvmTiEnv* env,
542 ArtJvmtiEvent event) {
543 jvmtiCapabilities caps = env->capabilities;
544 switch (event) {
545 case ArtJvmtiEvent::kBreakpoint:
546 return caps.can_generate_breakpoint_events == 1;
547
548 case ArtJvmtiEvent::kCompiledMethodLoad:
549 case ArtJvmtiEvent::kCompiledMethodUnload:
550 return caps.can_generate_compiled_method_load_events == 1;
551
552 case ArtJvmtiEvent::kException:
553 case ArtJvmtiEvent::kExceptionCatch:
554 return caps.can_generate_exception_events == 1;
555
556 case ArtJvmtiEvent::kFieldAccess:
557 return caps.can_generate_field_access_events == 1;
558
559 case ArtJvmtiEvent::kFieldModification:
560 return caps.can_generate_field_modification_events == 1;
561
562 case ArtJvmtiEvent::kFramePop:
563 return caps.can_generate_frame_pop_events == 1;
564
565 case ArtJvmtiEvent::kGarbageCollectionStart:
566 case ArtJvmtiEvent::kGarbageCollectionFinish:
567 return caps.can_generate_garbage_collection_events == 1;
568
569 case ArtJvmtiEvent::kMethodEntry:
570 return caps.can_generate_method_entry_events == 1;
571
572 case ArtJvmtiEvent::kMethodExit:
573 return caps.can_generate_method_exit_events == 1;
574
575 case ArtJvmtiEvent::kMonitorContendedEnter:
576 case ArtJvmtiEvent::kMonitorContendedEntered:
577 case ArtJvmtiEvent::kMonitorWait:
578 case ArtJvmtiEvent::kMonitorWaited:
579 return caps.can_generate_monitor_events == 1;
580
581 case ArtJvmtiEvent::kNativeMethodBind:
582 return caps.can_generate_native_method_bind_events == 1;
583
584 case ArtJvmtiEvent::kObjectFree:
585 return caps.can_generate_object_free_events == 1;
586
587 case ArtJvmtiEvent::kSingleStep:
588 return caps.can_generate_single_step_events == 1;
589
590 case ArtJvmtiEvent::kVmObjectAlloc:
591 return caps.can_generate_vm_object_alloc_events == 1;
592
593 default:
594 return true;
595 }
596}
597
Andreas Gampe77708d92016-10-07 11:48:21 -0700598jvmtiError EventHandler::SetEvent(ArtJvmTiEnv* env,
599 art::Thread* thread,
Alex Light40d87f42017-01-18 10:27:06 -0800600 ArtJvmtiEvent event,
Andreas Gampe77708d92016-10-07 11:48:21 -0700601 jvmtiEventMode mode) {
602 if (thread != nullptr) {
603 art::ThreadState state = thread->GetState();
604 if (state == art::ThreadState::kStarting ||
605 state == art::ThreadState::kTerminated ||
606 thread->IsStillStarting()) {
607 return ERR(THREAD_NOT_ALIVE);
608 }
609 if (!IsThreadControllable(event)) {
610 return ERR(ILLEGAL_ARGUMENT);
611 }
612 }
613
Andreas Gampe77708d92016-10-07 11:48:21 -0700614 if (mode != JVMTI_ENABLE && mode != JVMTI_DISABLE) {
615 return ERR(ILLEGAL_ARGUMENT);
616 }
617
618 if (!EventMask::EventIsInRange(event)) {
619 return ERR(INVALID_EVENT_TYPE);
620 }
621
Alex Light9db679d2017-01-25 15:28:04 -0800622 if (!HasAssociatedCapability(env, event)) {
623 return ERR(MUST_POSSESS_CAPABILITY);
624 }
625
Andreas Gampe8b862ff2016-10-17 17:49:59 -0700626 bool old_state = global_mask.Test(event);
627
Andreas Gampe77708d92016-10-07 11:48:21 -0700628 if (mode == JVMTI_ENABLE) {
629 env->event_masks.EnableEvent(thread, event);
630 global_mask.Set(event);
631 } else {
632 DCHECK_EQ(mode, JVMTI_DISABLE);
633
634 env->event_masks.DisableEvent(thread, event);
Alex Light73afd322017-01-18 11:17:47 -0800635 RecalculateGlobalEventMask(event);
Andreas Gampe77708d92016-10-07 11:48:21 -0700636 }
637
Andreas Gampe8b862ff2016-10-17 17:49:59 -0700638 bool new_state = global_mask.Test(event);
639
Andreas Gampe77708d92016-10-07 11:48:21 -0700640 // Handle any special work required for the event type.
Andreas Gampe8b862ff2016-10-17 17:49:59 -0700641 if (new_state != old_state) {
642 HandleEventType(event, mode == JVMTI_ENABLE);
643 }
Andreas Gampe77708d92016-10-07 11:48:21 -0700644
645 return ERR(NONE);
646}
647
Alex Lightb7edcda2017-04-27 13:20:31 -0700648void EventHandler::Shutdown() {
649 // Need to remove the method_trace_listener_ if it's there.
650 art::Thread* self = art::Thread::Current();
651 art::gc::ScopedGCCriticalSection gcs(self,
652 art::gc::kGcCauseInstrumentation,
653 art::gc::kCollectorTypeInstrumentation);
654 art::ScopedSuspendAll ssa("jvmti method tracing uninstallation");
655 // Just remove every possible event.
656 art::Runtime::Current()->GetInstrumentation()->RemoveListener(method_trace_listener_.get(), ~0);
657}
658
Andreas Gampe27fa96c2016-10-07 15:05:24 -0700659EventHandler::EventHandler() {
660 alloc_listener_.reset(new JvmtiAllocationListener(this));
Andreas Gampe9b8c5882016-10-21 15:27:46 -0700661 gc_pause_listener_.reset(new JvmtiGcPauseListener(this));
Alex Lightb7edcda2017-04-27 13:20:31 -0700662 method_trace_listener_.reset(new JvmtiMethodTraceListener(this));
Andreas Gampe27fa96c2016-10-07 15:05:24 -0700663}
664
665EventHandler::~EventHandler() {
666}
667
Andreas Gampe77708d92016-10-07 11:48:21 -0700668} // namespace openjdkjvmti