31 #include "jfr/recorder/storage/jfrStorageUtils.inline.hpp" |
31 #include "jfr/recorder/storage/jfrStorageUtils.inline.hpp" |
32 #include "jfr/recorder/stringpool/jfrStringPool.hpp" |
32 #include "jfr/recorder/stringpool/jfrStringPool.hpp" |
33 #include "jfr/recorder/stringpool/jfrStringPoolWriter.hpp" |
33 #include "jfr/recorder/stringpool/jfrStringPoolWriter.hpp" |
34 #include "jfr/utilities/jfrTypes.hpp" |
34 #include "jfr/utilities/jfrTypes.hpp" |
35 #include "logging/log.hpp" |
35 #include "logging/log.hpp" |
36 #include "runtime/atomic.hpp" |
|
37 #include "runtime/mutexLocker.hpp" |
36 #include "runtime/mutexLocker.hpp" |
38 #include "runtime/orderAccess.hpp" |
37 #include "runtime/orderAccess.hpp" |
39 #include "runtime/safepoint.hpp" |
38 #include "runtime/safepoint.hpp" |
40 #include "runtime/thread.inline.hpp" |
39 #include "runtime/thread.inline.hpp" |
41 |
40 |
42 typedef JfrStringPool::Buffer* BufferPtr; |
41 typedef JfrStringPool::Buffer* BufferPtr; |
43 |
42 |
44 static JfrStringPool* _instance = NULL; |
43 static JfrStringPool* _instance = NULL; |
|
44 static uint64_t store_generation = 0; |
|
45 static uint64_t serialized_generation = 0; |
|
46 |
|
47 inline void set_generation(uint64_t value, uint64_t* const dest) { |
|
48 assert(dest != NULL, "invariant"); |
|
49 OrderAccess::release_store(dest, value); |
|
50 } |
|
51 static void increment_store_generation() { |
|
52 const uint64_t current_serialized = OrderAccess::load_acquire(&serialized_generation); |
|
53 const uint64_t current_stored = OrderAccess::load_acquire(&store_generation); |
|
54 if (current_serialized == current_stored) { |
|
55 set_generation(current_serialized + 1, &store_generation); |
|
56 } |
|
57 } |
|
58 |
|
59 static bool increment_serialized_generation() { |
|
60 const uint64_t current_stored = OrderAccess::load_acquire(&store_generation); |
|
61 const uint64_t current_serialized = OrderAccess::load_acquire(&serialized_generation); |
|
62 if (current_stored != current_serialized) { |
|
63 set_generation(current_stored, &serialized_generation); |
|
64 return true; |
|
65 } |
|
66 return false; |
|
67 } |
|
68 |
|
69 bool JfrStringPool::is_modified() { |
|
70 return increment_serialized_generation(); |
|
71 } |
45 |
72 |
46 JfrStringPool& JfrStringPool::instance() { |
73 JfrStringPool& JfrStringPool::instance() { |
47 return *_instance; |
74 return *_instance; |
48 } |
75 } |
49 |
76 |
50 JfrStringPool* JfrStringPool::create(JfrChunkWriter& cw) { |
77 JfrStringPool* JfrStringPool::create(JfrChunkWriter& cw) { |
|
78 store_generation = 0; |
|
79 serialized_generation = 0; |
51 assert(_instance == NULL, "invariant"); |
80 assert(_instance == NULL, "invariant"); |
52 _instance = new JfrStringPool(cw); |
81 _instance = new JfrStringPool(cw); |
53 return _instance; |
82 return _instance; |
54 } |
83 } |
55 |
84 |
129 } |
158 } |
130 |
159 |
131 bool JfrStringPool::add(bool epoch, jlong id, jstring string, JavaThread* jt) { |
160 bool JfrStringPool::add(bool epoch, jlong id, jstring string, JavaThread* jt) { |
132 assert(jt != NULL, "invariant"); |
161 assert(jt != NULL, "invariant"); |
133 const bool current_epoch = JfrTraceIdEpoch::epoch(); |
162 const bool current_epoch = JfrTraceIdEpoch::epoch(); |
134 if (current_epoch == epoch) { |
163 if (current_epoch != epoch) { |
|
164 return current_epoch; |
|
165 } |
|
166 { |
135 JfrStringPoolWriter writer(jt); |
167 JfrStringPoolWriter writer(jt); |
136 writer.write(id); |
168 writer.write(id); |
137 writer.write(string); |
169 writer.write(string); |
138 writer.inc_nof_strings(); |
170 writer.inc_nof_strings(); |
139 } |
171 } |
|
172 increment_store_generation(); |
140 return current_epoch; |
173 return current_epoch; |
141 } |
174 } |
142 |
175 |
143 template <template <typename> class Operation> |
176 template <template <typename> class Operation> |
144 class StringPoolOp { |
177 class StringPoolOp { |
161 return _op.write(buffer, data, size); |
194 return _op.write(buffer, data, size); |
162 } |
195 } |
163 size_t processed() { return _strings_processed; } |
196 size_t processed() { return _strings_processed; } |
164 }; |
197 }; |
165 |
198 |
166 template <typename Type> |
199 template <typename T> |
167 class StringPoolDiscarderStub { |
200 class StringPoolDiscarderStub { |
168 public: |
201 public: |
|
202 typedef T Type; |
169 bool write(Type* buffer, const u1* data, size_t size) { |
203 bool write(Type* buffer, const u1* data, size_t size) { |
170 // stub only, discard happens at higher level |
204 // stub only, discard happens at higher level |
171 return true; |
205 return true; |
172 } |
206 } |
173 }; |
207 }; |
195 assert(SafepointSynchronize::is_at_safepoint(), "invariant"); |
229 assert(SafepointSynchronize::is_at_safepoint(), "invariant"); |
196 return write(); |
230 return write(); |
197 } |
231 } |
198 |
232 |
199 size_t JfrStringPool::clear() { |
233 size_t JfrStringPool::clear() { |
|
234 increment_serialized_generation(); |
200 DiscardOperation discard_operation; |
235 DiscardOperation discard_operation; |
201 ExclusiveDiscardOperation edo(discard_operation); |
236 ExclusiveDiscardOperation edo(discard_operation); |
202 StringPoolReleaseOperation spro(_free_list_mspace, Thread::current(), false); |
237 StringPoolReleaseOperation spro(_free_list_mspace, Thread::current(), false); |
203 StringPoolDiscardOperation spdo(&edo, &spro); |
238 StringPoolDiscardOperation spdo(&edo, &spro); |
204 assert(_free_list_mspace->is_full_empty(), "invariant"); |
239 assert(_free_list_mspace->is_full_empty(), "invariant"); |