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_JFRTRACEIDBITS_INLINE_HPP
26 #define SHARE_JFR_RECORDER_CHECKPOINT_TYPES_TRACEID_JFRTRACEIDBITS_INLINE_HPP
27
28 #include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdBits.hpp"
29
30 #include "oops/method.hpp"
31 #include "runtime/atomic.hpp"
32 #include "utilities/macros.hpp"
33
34 #ifdef VM_LITTLE_ENDIAN
35 const int low_offset = 0;
36 const int meta_offset = low_offset + 1;
37 #else
38 const int low_offset = 7;
39 const int meta_offset = low_offset - 1;
40 #endif
41
low_addr(jbyte * addr)42 inline jbyte* low_addr(jbyte* addr) {
43 assert(addr != NULL, "invariant");
44 return addr + low_offset;
45 }
46
low_addr(traceid * addr)47 inline jbyte* low_addr(traceid* addr) {
48 return low_addr((jbyte*)addr);
49 }
50
meta_addr(jbyte * addr)51 inline jbyte* meta_addr(jbyte* addr) {
52 assert(addr != NULL, "invariant");
53 return addr + meta_offset;
54 }
55
meta_addr(traceid * addr)56 inline jbyte* meta_addr(traceid* addr) {
57 return meta_addr((jbyte*)addr);
58 }
59
60 template <typename T>
traceid_tag_byte(const T * ptr)61 inline jbyte* traceid_tag_byte(const T* ptr) {
62 assert(ptr != NULL, "invariant");
63 return low_addr(ptr->trace_id_addr());
64 }
65
66 template <>
traceid_tag_byte(const Method * ptr)67 inline jbyte* traceid_tag_byte<Method>(const Method* ptr) {
68 assert(ptr != NULL, "invariant");
69 return ptr->trace_flags_addr();
70 }
71
72 template <typename T>
traceid_meta_byte(const T * ptr)73 inline jbyte* traceid_meta_byte(const T* ptr) {
74 assert(ptr != NULL, "invariant");
75 return meta_addr(ptr->trace_id_addr());
76 }
77
78 template <>
traceid_meta_byte(const Method * ptr)79 inline jbyte* traceid_meta_byte<Method>(const Method* ptr) {
80 assert(ptr != NULL, "invariant");
81 return ptr->trace_meta_addr();
82 }
83
traceid_and(jbyte bits,jbyte current)84 inline jbyte traceid_and(jbyte bits, jbyte current) {
85 return bits & current;
86 }
87
traceid_or(jbyte bits,jbyte current)88 inline jbyte traceid_or(jbyte bits, jbyte current) {
89 return bits | current;
90 }
91
traceid_xor(jbyte bits,jbyte current)92 inline jbyte traceid_xor(jbyte bits, jbyte current) {
93 return bits ^ current;
94 }
95
96 template <jbyte op(jbyte, jbyte)>
set_form(jbyte bits,jbyte * dest)97 inline void set_form(jbyte bits, jbyte* dest) {
98 assert(dest != NULL, "invariant");
99 *dest = op(bits, *dest);
100 OrderAccess::storestore();
101 }
102
103 template <jbyte op(jbyte, jbyte)>
set_cas_form(jbyte bits,jbyte volatile * dest)104 inline void set_cas_form(jbyte bits, jbyte volatile* dest) {
105 assert(dest != NULL, "invariant");
106 do {
107 const jbyte current = *dest;
108 const jbyte new_value = op(bits, current);
109 if (current == new_value || Atomic::cmpxchg(dest, current, new_value) == current) {
110 return;
111 }
112 } while (true);
113 }
114
115 template <typename T>
cas(jbyte bits,const T * ptr)116 inline void JfrTraceIdBits::cas(jbyte bits, const T* ptr) {
117 assert(ptr != NULL, "invariant");
118 set_cas_form<traceid_or>(bits, traceid_tag_byte(ptr));
119 }
120
121 template <typename T>
load(const T * ptr)122 inline traceid JfrTraceIdBits::load(const T* ptr) {
123 assert(ptr != NULL, "invariant");
124 return ptr->trace_id();
125 }
126
set(jbyte bits,jbyte * dest)127 inline void set(jbyte bits, jbyte* dest) {
128 assert(dest != NULL, "invariant");
129 set_form<traceid_or>(bits, dest);
130 }
131
132 template <typename T>
store(jbyte bits,const T * ptr)133 inline void JfrTraceIdBits::store(jbyte bits, const T* ptr) {
134 assert(ptr != NULL, "invariant");
135 set(bits, traceid_tag_byte(ptr));
136 }
137
138 template <typename T>
meta_store(jbyte bits,const T * ptr)139 inline void JfrTraceIdBits::meta_store(jbyte bits, const T* ptr) {
140 assert(ptr != NULL, "invariant");
141 set(bits, traceid_meta_byte(ptr));
142 }
143
set_mask(jbyte mask,jbyte * dest)144 inline void set_mask(jbyte mask, jbyte* dest) {
145 set_cas_form<traceid_and>(mask, dest);
146 }
147
148 template <typename T>
mask_store(jbyte mask,const T * ptr)149 inline void JfrTraceIdBits::mask_store(jbyte mask, const T* ptr) {
150 assert(ptr != NULL, "invariant");
151 set_mask(mask, traceid_tag_byte(ptr));
152 }
153
154 template <typename T>
meta_mask_store(jbyte mask,const T * ptr)155 inline void JfrTraceIdBits::meta_mask_store(jbyte mask, const T* ptr) {
156 assert(ptr != NULL, "invariant");
157 set_mask(mask, traceid_meta_byte(ptr));
158 }
159
clear_bits(jbyte bits,jbyte * dest)160 inline void clear_bits(jbyte bits, jbyte* dest) {
161 set_form<traceid_xor>(bits, dest);
162 }
163
164 template <typename T>
clear(jbyte bits,const T * ptr)165 inline void JfrTraceIdBits::clear(jbyte bits, const T* ptr) {
166 assert(ptr != NULL, "invariant");
167 clear_bits(bits, traceid_tag_byte(ptr));
168 }
169
clear_bits_cas(jbyte bits,jbyte * dest)170 inline void clear_bits_cas(jbyte bits, jbyte* dest) {
171 set_cas_form<traceid_xor>(bits, dest);
172 }
173
174 template <typename T>
clear_cas(jbyte bits,const T * ptr)175 inline void JfrTraceIdBits::clear_cas(jbyte bits, const T* ptr) {
176 assert(ptr != NULL, "invariant");
177 clear_bits_cas(bits, traceid_tag_byte(ptr));
178 }
179
180 template <typename T>
meta_clear(jbyte bits,const T * ptr)181 inline void JfrTraceIdBits::meta_clear(jbyte bits, const T* ptr) {
182 assert(ptr != NULL, "invariant");
183 clear_bits(bits, traceid_meta_byte(ptr));
184 }
185
186 #endif // SHARE_JFR_RECORDER_CHECKPOINT_TYPES_TRACEID_JFRTRACEIDBITS_INLINE_HPP
187