/* * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved. * * This file is part of the Lock Contention Tracing Subsystem for the HotSpot * Virtual Machine, which is developed at Christian Doppler Laboratory on * Monitoring and Evolution of Very-Large-Scale Software Systems. Please * contact us at if you need additional information * or have any questions. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work. If not, see . * */ #ifndef SHARE_VM_EVTRACE_TRACEMETADATA_INLINE_HPP #define SHARE_VM_EVTRACE_TRACEMETADATA_INLINE_HPP #include "runtime/thread.hpp" #include "runtime/objectMonitor.hpp" #include "runtime/objectMonitor.inline.hpp" #include "jvmtifiles/jvmtiEnv.hpp" inline TraceTypes::timestamp TraceMetadata::time_now() { return (TraceTypes::timestamp) os::javaTimeNanos(); } inline TraceTypes::thread_id TraceMetadata::thread_id(Thread *t) { assert(t != NULL, "thread is NULL"); if (t->is_Java_thread()) { JavaThread *jt = (JavaThread *) t; return (TraceTypes::thread_id) java_lang_Thread::thread_id(jt->threadObj()); } return (TraceTypes::thread_id) -t->osthread()->thread_identifier(); } inline TraceTypes::object_id TraceMetadata::object_id(oop obj) { assert(obj != NULL, "object is NULL"); return (TraceTypes::object_id) obj->identity_hash(); } inline TraceTypes::objmonitor_id TraceMetadata::objmonitor_id(ObjectMonitor* m) { assert(m != NULL, "object monitor is NULL"); // NOTE: object monitors are native objects and are not moved by the garbage collector, so // they can be identified by their address. However, monitors are allocated from pools and // recycled after an object dies or on deflation. We must take this lifecycle into account // when associating object monitors with objects. return (TraceTypes::objmonitor_id) (intptr_t) m; } inline TraceTypes::object_id TraceMetadata::objmonitor_object_id(ObjectMonitor* m) { assert(m != NULL, "object monitor is NULL"); if (m->header()->has_no_hash()) { oop obj = (oop) m->object(); return (TraceTypes::object_id) obj->identity_hash(); } return (TraceTypes::object_id) m->header()->hash(); } inline TraceTypes::thread_state TraceMetadata::thread_state(Thread *t) { assert(t != NULL, "thread is NULL"); assert(t->is_Java_thread(), "only Java threads supported"); // just use JVMTI thread states JavaThread *jt = (JavaThread *) t; TraceTypes::thread_state state = 0; if (jt->threadObj() != NULL) { // provides most state bits state = (TraceTypes::thread_state) java_lang_Thread::get_thread_status(jt->threadObj()); } // additional state bits if (jt->is_ext_suspended() || jt->is_external_suspend()) { // same as is_being_ext_suspended() but without locking state |= JVMTI_THREAD_STATE_SUSPENDED; } JavaThreadState jts = jt->thread_state(); if (jts == _thread_in_native) { state |= JVMTI_THREAD_STATE_IN_NATIVE; } OSThread* osThread = jt->osthread(); if (osThread != NULL && osThread->interrupted()) { state |= JVMTI_THREAD_STATE_INTERRUPTED; } return state; } inline TraceTypes::classloader_id TraceMetadata::classloader_id(ClassLoaderData* cld) { return (TraceTypes::classloader_id) (intptr_t) cld; } inline TraceTypes::class_id TraceMetadata::class_id(Klass *klass, bool &added) { added = false; if (!klass->is_tracing_known()) { added = klass->atomic_mark_tracing_known(); } return (TraceTypes::class_id) (intptr_t) klass; } inline TraceTypes::method_id TraceMetadata::method_id(Method* method, bool& added) { assert(method->method_holder()->is_tracing_known(), "klass must be known"); added = false; if (!method->is_tracing_known()) { added = method->atomic_mark_tracing_known(); } return (TraceTypes::method_id) (intptr_t) method; } inline TraceTypes::stack_id TraceMetadata::next_stack_id() { assert(EnableEventTracingStackTraces, "stack traces not enabled"); return (TraceTypes::stack_id) Atomic::add_ptr(1, &_last_stack_id); } inline TraceTypes::seq_num TraceMetadata::next_global_seq() { return (TraceTypes::seq_num) Atomic::add_ptr(1, &_last_global_seq); } inline const CachedTraceStack * TraceMetadata::get_or_try_add_stack(CompositeTraceStack &ts, bool &known, TraceTypes::stack_id preallocated_id) { return _stack_cache->get_or_try_add(ts, known, preallocated_id); } inline void TraceMetadata::purge_unloading_classes(ClassLoaderData *loader) { _stack_cache->purge_unloading_classes(loader); } inline void TraceMetadata::purge_unloading_nmethod(const nmethod *nm) { _stack_cache->purge_unloading_nmethod(nm); } #endif /* SHARE_VM_EVTRACE_TRACEMETADATA_INLINE_HPP */