1 /*
   2  * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
   3  *
   4  * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
   5  * Virtual Machine, which is developed at Christian Doppler Laboratory on
   6  * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
   7  * contact us at <http://mevss.jku.at/> if you need additional information
   8  * or have any questions.
   9  *
  10  * This code is free software; you can redistribute it and/or modify it
  11  * under the terms of the GNU General Public License version 2 only, as
  12  * published by the Free Software Foundation.
  13  *
  14  * This code is distributed in the hope that it will be useful, but WITHOUT
  15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  16  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  17  * version 2 for more details (a copy is included in the LICENSE file that
  18  * accompanied this code).
  19  *
  20  * You should have received a copy of the GNU General Public License version
  21  * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
  22  *
  23  */
  24 
  25 #ifndef SHARE_VM_EVTRACE_TRACEMETADATA_INLINE_HPP
  26 #define SHARE_VM_EVTRACE_TRACEMETADATA_INLINE_HPP
  27 
  28 #include "runtime/thread.hpp"
  29 #include "runtime/objectMonitor.hpp"
  30 #include "runtime/objectMonitor.inline.hpp"
  31 #include "jvmtifiles/jvmtiEnv.hpp"
  32 
  33 inline TraceTypes::timestamp TraceMetadata::time_now() {
  34   return (TraceTypes::timestamp) os::javaTimeNanos();
  35 }
  36 
  37 inline TraceTypes::thread_id TraceMetadata::thread_id(Thread *t) {
  38   assert(t != NULL, "thread is NULL");
  39   if (t->is_Java_thread()) {
  40     JavaThread *jt = (JavaThread *) t;
  41     return (TraceTypes::thread_id) java_lang_Thread::thread_id(jt->threadObj());
  42   }
  43   return (TraceTypes::thread_id) -t->osthread()->thread_identifier();
  44 }
  45 
  46 inline TraceTypes::object_id TraceMetadata::object_id(oop obj) {
  47   assert(obj != NULL, "object is NULL");
  48   return (TraceTypes::object_id) obj->identity_hash();
  49 }
  50 
  51 inline TraceTypes::objmonitor_id TraceMetadata::objmonitor_id(ObjectMonitor* m) {
  52   assert(m != NULL, "object monitor is NULL");
  53   // NOTE: object monitors are native objects and are not moved by the garbage collector, so
  54   // they can be identified by their address. However, monitors are allocated from pools and
  55   // recycled after an object dies or on deflation. We must take this lifecycle into account
  56   // when associating object monitors with objects.
  57   return (TraceTypes::objmonitor_id) (intptr_t) m;
  58 }
  59 
  60 inline TraceTypes::object_id TraceMetadata::objmonitor_object_id(ObjectMonitor* m) {
  61   assert(m != NULL, "object monitor is NULL");
  62   if (m->header()->has_no_hash()) {
  63     oop obj = (oop) m->object();
  64     return (TraceTypes::object_id) obj->identity_hash();
  65   }
  66   return (TraceTypes::object_id) m->header()->hash();
  67 }
  68 
  69 inline TraceTypes::thread_state TraceMetadata::thread_state(Thread *t) {
  70   assert(t != NULL, "thread is NULL");
  71   assert(t->is_Java_thread(), "only Java threads supported");
  72 
  73   // just use JVMTI thread states
  74   JavaThread *jt = (JavaThread *) t;
  75   TraceTypes::thread_state state = 0;
  76   if (jt->threadObj() != NULL) { // provides most state bits
  77     state = (TraceTypes::thread_state) java_lang_Thread::get_thread_status(jt->threadObj());
  78   }
  79   // additional state bits
  80   if (jt->is_ext_suspended() || jt->is_external_suspend()) { // same as is_being_ext_suspended() but without locking
  81     state |= JVMTI_THREAD_STATE_SUSPENDED;
  82   }
  83   JavaThreadState jts = jt->thread_state();
  84   if (jts == _thread_in_native) {
  85     state |= JVMTI_THREAD_STATE_IN_NATIVE;
  86   }
  87   OSThread* osThread = jt->osthread();
  88   if (osThread != NULL && osThread->interrupted()) {
  89     state |= JVMTI_THREAD_STATE_INTERRUPTED;
  90   }
  91   return state;
  92 }
  93 
  94 inline TraceTypes::classloader_id TraceMetadata::classloader_id(ClassLoaderData* cld) {
  95   return (TraceTypes::classloader_id) (intptr_t) cld;
  96 }
  97 
  98 inline TraceTypes::class_id TraceMetadata::class_id(Klass *klass, bool &added) {
  99   added = false;
 100   if (!klass->is_tracing_known()) {
 101     added = klass->atomic_mark_tracing_known();
 102   }
 103   return (TraceTypes::class_id) (intptr_t) klass;
 104 }
 105 
 106 inline TraceTypes::method_id TraceMetadata::method_id(Method* method, bool& added) {
 107   assert(method->method_holder()->is_tracing_known(), "klass must be known");
 108 
 109   added = false;
 110   if (!method->is_tracing_known()) {
 111     added = method->atomic_mark_tracing_known();
 112   }
 113   return (TraceTypes::method_id) (intptr_t) method;
 114 }
 115 
 116 inline TraceTypes::stack_id TraceMetadata::next_stack_id() {
 117   assert(EnableEventTracingStackTraces, "stack traces not enabled");
 118   return (TraceTypes::stack_id) Atomic::add_ptr(1, &_last_stack_id);
 119 }
 120 
 121 inline TraceTypes::seq_num TraceMetadata::next_global_seq() {
 122   return (TraceTypes::seq_num) Atomic::add_ptr(1, &_last_global_seq);
 123 }
 124 
 125 inline const CachedTraceStack * TraceMetadata::get_or_try_add_stack(CompositeTraceStack &ts, bool &known, TraceTypes::stack_id preallocated_id) {
 126   return _stack_cache->get_or_try_add(ts, known, preallocated_id);
 127 }
 128 
 129 inline void TraceMetadata::purge_unloading_classes(ClassLoaderData *loader) {
 130   _stack_cache->purge_unloading_classes(loader);
 131 }
 132 
 133 inline void TraceMetadata::purge_unloading_nmethod(const nmethod *nm) {
 134   _stack_cache->purge_unloading_nmethod(nm);
 135 }
 136 
 137 #endif /* SHARE_VM_EVTRACE_TRACEMETADATA_INLINE_HPP */