1 /* 2 * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef SHARE_JFR_RECORDER_CHECKPOINT_TYPES_TRACEID_JFRTRACEID_INLINE_HPP 26 #define SHARE_JFR_RECORDER_CHECKPOINT_TYPES_TRACEID_JFRTRACEID_INLINE_HPP 27 28 #include "classfile/classLoaderData.hpp" 29 #include "classfile/moduleEntry.hpp" 30 #include "classfile/packageEntry.hpp" 31 #include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp" 32 #include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdBits.inline.hpp" 33 #include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp" 34 #include "jfr/support/jfrKlassExtension.hpp" 35 #include "oops/arrayKlass.hpp" 36 #include "oops/klass.hpp" 37 #include "oops/instanceKlass.hpp" 38 #include "oops/method.hpp" 39 #include "runtime/thread.inline.hpp" 40 #include "utilities/debug.hpp" 41 42 inline bool is_not_tagged(traceid value) { 43 const traceid this_epoch_bit = JfrTraceIdEpoch::in_use_this_epoch_bit(); 44 return (value & ((this_epoch_bit << META_SHIFT) | this_epoch_bit)) != this_epoch_bit; 45 } 46 47 template <typename T> 48 inline bool should_tag(const T* t) { 49 assert(t != NULL, "invariant"); 50 return is_not_tagged(TRACE_ID_RAW(t)); 51 } 52 53 template <> 54 inline bool should_tag<Method>(const Method* method) { 55 assert(method != NULL, "invariant"); 56 return is_not_tagged((traceid)method->trace_flags()); 57 } 58 59 template <typename T> 60 inline traceid set_used_and_get(const T* type) { 61 assert(type != NULL, "invariant"); 62 if (should_tag(type)) { 63 SET_USED_THIS_EPOCH(type); 64 JfrTraceIdEpoch::set_changed_tag_state(); 65 } 66 assert(USED_THIS_EPOCH(type), "invariant"); 67 return TRACE_ID(type); 68 } 69 70 inline traceid JfrTraceId::get(const Klass* klass) { 71 assert(klass != NULL, "invariant"); 72 return TRACE_ID(klass); 73 } 74 75 inline traceid JfrTraceId::get(const Thread* t) { 76 assert(t != NULL, "invariant"); 77 return TRACE_ID_RAW(t->jfr_thread_local()); 78 } 79 80 inline traceid JfrTraceId::use(const Klass* klass) { 81 assert(klass != NULL, "invariant"); 82 if (should_tag(klass)) { 83 SET_USED_THIS_EPOCH(klass); 84 JfrTraceIdEpoch::set_changed_tag_state(); 85 } 86 assert(USED_THIS_EPOCH(klass), "invariant"); 87 return get(klass); 88 } 89 90 inline traceid JfrTraceId::use(const Method* method) { 91 return use(method->method_holder(), method); 92 } 93 94 inline traceid JfrTraceId::use(const Klass* klass, const Method* method) { 95 assert(klass != NULL, "invariant"); 96 assert(method != NULL, "invariant"); 97 if (METHOD_FLAG_NOT_USED_THIS_EPOCH(method)) { 98 SET_METHOD_AND_CLASS_USED_THIS_EPOCH(klass); 99 SET_METHOD_FLAG_USED_THIS_EPOCH(method); 100 assert(METHOD_AND_CLASS_USED_THIS_EPOCH(klass), "invariant"); 101 assert(METHOD_FLAG_USED_THIS_EPOCH(method), "invariant"); 102 JfrTraceIdEpoch::set_changed_tag_state(); 103 } 104 return (METHOD_ID(klass, method)); 105 } 106 107 inline traceid JfrTraceId::use(const ModuleEntry* module) { 108 return set_used_and_get(module); 109 } 110 111 inline traceid JfrTraceId::use(const PackageEntry* package) { 112 return set_used_and_get(package); 113 } 114 115 inline traceid JfrTraceId::use(const ClassLoaderData* cld) { 116 assert(cld != NULL, "invariant"); 117 return cld->has_class_mirror_holder() ? 0 : set_used_and_get(cld); 118 } 119 120 inline void JfrTraceId::set_leakp(const Klass* klass, const Method* method) { 121 assert(klass != NULL, "invariant"); 122 assert(METHOD_AND_CLASS_USED_THIS_EPOCH(klass), "invariant"); 123 assert(method != NULL, "invariant"); 124 assert(klass == method->method_holder(), "invariant"); 125 if (METHOD_FLAG_NOT_USED_THIS_EPOCH(method)) { 126 // the method is already logically tagged, just like the klass, 127 // but because of redefinition, the latest Method* 128 // representation might not have a reified tag. 129 SET_METHOD_FLAG_USED_THIS_EPOCH(method); 130 assert(METHOD_FLAG_USED_THIS_EPOCH(method), "invariant"); 131 } 132 SET_LEAKP(klass); 133 SET_METHOD_LEAKP(method); 134 } 135 136 inline bool JfrTraceId::in_visible_set(const Klass* klass) { 137 assert(klass != NULL, "invariant"); 138 assert(((JavaThread*)Thread::current())->thread_state() == _thread_in_vm, "invariant"); 139 return (IS_JDK_JFR_EVENT_SUBKLASS(klass) && !klass->is_abstract()) || IS_EVENT_HOST_KLASS(klass); 140 } 141 142 inline bool JfrTraceId::is_jdk_jfr_event(const Klass* k) { 143 assert(k != NULL, "invariant"); 144 return IS_JDK_JFR_EVENT_KLASS(k); 145 } 146 147 inline void JfrTraceId::tag_as_jdk_jfr_event(const Klass* klass) { 148 assert(klass != NULL, "invariant"); 149 SET_JDK_JFR_EVENT_KLASS(klass); 150 assert(IS_JDK_JFR_EVENT_KLASS(klass), "invariant"); 151 } 152 153 inline bool JfrTraceId::is_jdk_jfr_event_sub(const Klass* k) { 154 assert(k != NULL, "invariant"); 155 return IS_JDK_JFR_EVENT_SUBKLASS(k); 156 } 157 158 inline void JfrTraceId::tag_as_jdk_jfr_event_sub(const Klass* k) { 159 assert(k != NULL, "invariant"); 160 if (IS_NOT_AN_EVENT_SUB_KLASS(k)) { 161 SET_JDK_JFR_EVENT_SUBKLASS(k); 162 } 163 assert(IS_JDK_JFR_EVENT_SUBKLASS(k), "invariant"); 164 } 165 166 inline bool JfrTraceId::in_jdk_jfr_event_hierarchy(const Klass* klass) { 167 assert(klass != NULL, "invariant"); 168 if (is_jdk_jfr_event(klass)) { 169 return true; 170 } 171 const Klass* const super = klass->super(); 172 return super != NULL ? IS_EVENT_KLASS(super) : false; 173 } 174 175 inline bool JfrTraceId::is_event_host(const Klass* k) { 176 assert(k != NULL, "invariant"); 177 return IS_EVENT_HOST_KLASS(k); 178 } 179 180 inline void JfrTraceId::tag_as_event_host(const Klass* k) { 181 assert(k != NULL, "invariant"); 182 SET_EVENT_HOST_KLASS(k); 183 assert(IS_EVENT_HOST_KLASS(k), "invariant"); 184 } 185 186 #endif // SHARE_JFR_RECORDER_CHECKPOINT_TYPES_TRACEID_JFRTRACEID_INLINE_HPP