30 #include "runtime/orderAccess.hpp" |
30 #include "runtime/orderAccess.hpp" |
31 #include "utilities/macros.hpp" |
31 #include "utilities/macros.hpp" |
32 |
32 |
33 #ifdef VM_LITTLE_ENDIAN |
33 #ifdef VM_LITTLE_ENDIAN |
34 static const int low_offset = 0; |
34 static const int low_offset = 0; |
35 static const int leakp_offset = low_offset + 1; |
35 static const int meta_offset = low_offset + 1; |
36 #else |
36 #else |
37 static const int low_offset = 7; |
37 static const int low_offset = 7; |
38 static const int leakp_offset = low_offset - 1; |
38 static const int meta_offset = low_offset - 1; |
39 #endif |
39 #endif |
40 |
40 |
41 inline void set_bits(jbyte bits, jbyte* const dest) { |
41 inline void set_bits(jbyte bits, jbyte* const dest) { |
42 assert(dest != NULL, "invariant"); |
42 assert(dest != NULL, "invariant"); |
43 const jbyte current = *dest; |
43 if (bits != (*dest & bits)) { |
44 if (bits != (current & bits)) { |
44 *dest |= bits; |
45 *dest = current | bits; |
|
46 |
|
47 OrderAccess::storestore(); |
45 OrderAccess::storestore(); |
48 } |
46 } |
49 } |
47 } |
50 |
48 |
51 inline void set_bits_cas(jbyte bits, jbyte* const dest) { |
49 inline jbyte traceid_and(jbyte current, jbyte bits) { |
|
50 return current & bits; |
|
51 } |
|
52 |
|
53 inline jbyte traceid_or(jbyte current, jbyte bits) { |
|
54 return current | bits; |
|
55 } |
|
56 |
|
57 inline jbyte traceid_xor(jbyte current, jbyte bits) { |
|
58 return current ^ bits; |
|
59 } |
|
60 |
|
61 template <jbyte op(jbyte, jbyte)> |
|
62 inline void set_bits_cas_form(jbyte bits, jbyte* const dest) { |
52 assert(dest != NULL, "invariant"); |
63 assert(dest != NULL, "invariant"); |
53 do { |
64 do { |
54 const jbyte current = OrderAccess::load_acquire(dest); |
65 const jbyte current = *dest; |
55 if (bits == (current & bits)) { |
66 const jbyte new_value = op(current, bits); |
56 return; |
|
57 } |
|
58 const jbyte new_value = current | bits; |
|
59 if (Atomic::cmpxchg(new_value, dest, current) == current) { |
67 if (Atomic::cmpxchg(new_value, dest, current) == current) { |
60 return; |
68 return; |
61 } |
69 } |
62 } while (true); |
70 } while (true); |
63 } |
71 } |
64 |
72 |
|
73 inline void set_bits_cas(jbyte bits, jbyte* const dest) { |
|
74 set_bits_cas_form<traceid_or>(bits, dest); |
|
75 } |
|
76 |
65 inline void clear_bits_cas(jbyte bits, jbyte* const dest) { |
77 inline void clear_bits_cas(jbyte bits, jbyte* const dest) { |
66 assert(dest != NULL, "invariant"); |
78 set_bits_cas_form<traceid_xor>(bits, dest); |
67 do { |
|
68 const jbyte current = OrderAccess::load_acquire(dest); |
|
69 if (bits != (current & bits)) { |
|
70 return; |
|
71 } |
|
72 const jbyte new_value = current ^ bits; |
|
73 if (Atomic::cmpxchg(new_value, dest, current) == current) { |
|
74 return; |
|
75 } |
|
76 } while (true); |
|
77 } |
79 } |
78 |
80 |
79 inline void set_mask(jbyte mask, jbyte* const dest) { |
81 inline void set_mask(jbyte mask, jbyte* const dest) { |
80 assert(dest != NULL, "invariant"); |
82 set_bits_cas_form<traceid_and>(mask, dest); |
81 const jbyte current = *dest; |
|
82 if (mask != (current & mask)) { |
|
83 *dest = current & mask; |
|
84 OrderAccess::storestore(); |
|
85 } |
|
86 } |
83 } |
87 inline void set_mask_cas(jbyte mask, jbyte* const dest) { |
84 |
88 assert(dest != NULL, "invariant"); |
|
89 do { |
|
90 const jbyte current = OrderAccess::load_acquire(dest); |
|
91 if (mask == (current & mask)) { |
|
92 return; |
|
93 } |
|
94 const jbyte new_value = current & mask; |
|
95 if (Atomic::cmpxchg(new_value, dest, current) == current) { |
|
96 return; |
|
97 } |
|
98 } while (true); |
|
99 } |
|
100 inline void set_traceid_bits(jbyte bits, traceid* dest) { |
85 inline void set_traceid_bits(jbyte bits, traceid* dest) { |
101 set_bits(bits, ((jbyte*)dest) + low_offset); |
86 set_bits(bits, ((jbyte*)dest) + low_offset); |
102 } |
87 } |
103 |
88 |
104 inline void set_traceid_bits_cas(jbyte bits, traceid* dest) { |
89 inline void set_traceid_bits_cas(jbyte bits, traceid* dest) { |
107 |
92 |
108 inline void set_traceid_mask(jbyte mask, traceid* dest) { |
93 inline void set_traceid_mask(jbyte mask, traceid* dest) { |
109 set_mask(mask, ((jbyte*)dest) + low_offset); |
94 set_mask(mask, ((jbyte*)dest) + low_offset); |
110 } |
95 } |
111 |
96 |
112 inline void set_leakp_traceid_bits(jbyte bits, traceid* dest) { |
97 inline void set_meta_bits(jbyte bits, jbyte* const dest) { |
113 set_bits(bits, ((jbyte*)dest) + leakp_offset); |
98 assert(dest != NULL, "invariant"); |
|
99 *dest |= bits; |
114 } |
100 } |
115 |
101 |
116 inline void set_leakp_traceid_bits_cas(jbyte bits, traceid* dest) { |
102 inline void set_traceid_meta_bits(jbyte bits, traceid* dest) { |
117 set_bits_cas(bits, ((jbyte*)dest) + leakp_offset); |
103 set_meta_bits(bits, ((jbyte*)dest) + meta_offset); |
118 } |
104 } |
119 |
105 |
120 inline void set_leakp_traceid_mask(jbyte mask, traceid* dest) { |
106 inline void set_meta_mask(jbyte mask, jbyte* const dest) { |
121 set_mask_cas(mask, ((jbyte*)dest) + leakp_offset); |
107 assert(dest != NULL, "invariant"); |
|
108 *dest &= mask; |
|
109 } |
|
110 |
|
111 inline void set_traceid_meta_mask(jbyte mask, traceid* dest) { |
|
112 set_meta_mask(mask, ((jbyte*)dest) + meta_offset); |
|
113 } |
|
114 |
|
115 // only used by a single thread with no visibility requirements |
|
116 inline void clear_meta_bits(jbyte bits, jbyte* const dest) { |
|
117 assert(dest != NULL, "invariant"); |
|
118 *dest ^= bits; |
122 } |
119 } |
123 |
120 |
124 #endif // SHARE_JFR_RECORDER_CHECKPOINT_TYPES_TRACEID_JFRTRACEIDBITS_INLINE_HPP |
121 #endif // SHARE_JFR_RECORDER_CHECKPOINT_TYPES_TRACEID_JFRTRACEIDBITS_INLINE_HPP |