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