/*
* 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 */