42 |
42 |
43 static JfrStringPool* _instance = NULL; |
43 static JfrStringPool* _instance = NULL; |
44 static uint64_t store_generation = 0; |
44 static uint64_t store_generation = 0; |
45 static uint64_t serialized_generation = 0; |
45 static uint64_t serialized_generation = 0; |
46 |
46 |
47 inline void set_value(uint64_t value, uint64_t* const dest) { |
47 inline void set_generation(uint64_t value, uint64_t* const dest) { |
48 assert(dest != NULL, "invariant"); |
48 assert(dest != NULL, "invariant"); |
49 const uint64_t current = OrderAccess::load_acquire(dest); |
49 OrderAccess::release_store(dest, value); |
50 if (value != current) { |
50 } |
51 OrderAccess::release_store(dest, value); |
51 static void increment_store_generation() { |
52 } |
52 const uint64_t current_serialized = OrderAccess::load_acquire(&serialized_generation); |
53 } |
53 const uint64_t current_stored = OrderAccess::load_acquire(&store_generation); |
54 static void inc_store_generation() { |
54 if (current_serialized == current_stored) { |
55 set_value(OrderAccess::load_acquire(&serialized_generation) + 1, &store_generation); |
55 set_generation(current_serialized + 1, &store_generation); |
56 } |
56 } |
57 static void set_serialized_generation() { |
57 } |
58 set_value(OrderAccess::load_acquire(&store_generation), &serialized_generation); |
58 |
59 } |
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 |
60 bool JfrStringPool::is_modified() { |
69 bool JfrStringPool::is_modified() { |
61 return serialized_generation != OrderAccess::load_acquire(&store_generation); |
70 return increment_serialized_generation(); |
62 } |
71 } |
|
72 |
63 JfrStringPool& JfrStringPool::instance() { |
73 JfrStringPool& JfrStringPool::instance() { |
64 return *_instance; |
74 return *_instance; |
65 } |
75 } |
66 |
76 |
67 JfrStringPool* JfrStringPool::create(JfrChunkWriter& cw) { |
77 JfrStringPool* JfrStringPool::create(JfrChunkWriter& cw) { |
148 } |
158 } |
149 |
159 |
150 bool JfrStringPool::add(bool epoch, jlong id, jstring string, JavaThread* jt) { |
160 bool JfrStringPool::add(bool epoch, jlong id, jstring string, JavaThread* jt) { |
151 assert(jt != NULL, "invariant"); |
161 assert(jt != NULL, "invariant"); |
152 const bool current_epoch = JfrTraceIdEpoch::epoch(); |
162 const bool current_epoch = JfrTraceIdEpoch::epoch(); |
153 if (current_epoch == epoch) { |
163 if (current_epoch != epoch) { |
|
164 return current_epoch; |
|
165 } |
|
166 { |
154 JfrStringPoolWriter writer(jt); |
167 JfrStringPoolWriter writer(jt); |
155 writer.write(id); |
168 writer.write(id); |
156 writer.write(string); |
169 writer.write(string); |
157 writer.inc_nof_strings(); |
170 writer.inc_nof_strings(); |
158 inc_store_generation(); |
171 } |
159 } |
172 increment_store_generation(); |
160 return current_epoch; |
173 return current_epoch; |
161 } |
174 } |
162 |
175 |
163 template <template <typename> class Operation> |
176 template <template <typename> class Operation> |
164 class StringPoolOp { |
177 class StringPoolOp { |
199 typedef ReleaseOp<JfrStringPoolMspace> StringPoolReleaseOperation; |
212 typedef ReleaseOp<JfrStringPoolMspace> StringPoolReleaseOperation; |
200 typedef CompositeOperation<ExclusiveWriteOperation, StringPoolReleaseOperation> StringPoolWriteOperation; |
213 typedef CompositeOperation<ExclusiveWriteOperation, StringPoolReleaseOperation> StringPoolWriteOperation; |
201 typedef CompositeOperation<ExclusiveDiscardOperation, StringPoolReleaseOperation> StringPoolDiscardOperation; |
214 typedef CompositeOperation<ExclusiveDiscardOperation, StringPoolReleaseOperation> StringPoolDiscardOperation; |
202 |
215 |
203 size_t JfrStringPool::write() { |
216 size_t JfrStringPool::write() { |
204 set_serialized_generation(); |
|
205 Thread* const thread = Thread::current(); |
217 Thread* const thread = Thread::current(); |
206 WriteOperation wo(_chunkwriter, thread); |
218 WriteOperation wo(_chunkwriter, thread); |
207 ExclusiveWriteOperation ewo(wo); |
219 ExclusiveWriteOperation ewo(wo); |
208 StringPoolReleaseOperation spro(_free_list_mspace, thread, false); |
220 StringPoolReleaseOperation spro(_free_list_mspace, thread, false); |
209 StringPoolWriteOperation spwo(&ewo, &spro); |
221 StringPoolWriteOperation spwo(&ewo, &spro); |
216 assert(SafepointSynchronize::is_at_safepoint(), "invariant"); |
228 assert(SafepointSynchronize::is_at_safepoint(), "invariant"); |
217 return write(); |
229 return write(); |
218 } |
230 } |
219 |
231 |
220 size_t JfrStringPool::clear() { |
232 size_t JfrStringPool::clear() { |
221 set_serialized_generation(); |
233 increment_serialized_generation(); |
222 DiscardOperation discard_operation; |
234 DiscardOperation discard_operation; |
223 ExclusiveDiscardOperation edo(discard_operation); |
235 ExclusiveDiscardOperation edo(discard_operation); |
224 StringPoolReleaseOperation spro(_free_list_mspace, Thread::current(), false); |
236 StringPoolReleaseOperation spro(_free_list_mspace, Thread::current(), false); |
225 StringPoolDiscardOperation spdo(&edo, &spro); |
237 StringPoolDiscardOperation spdo(&edo, &spro); |
226 assert(_free_list_mspace->is_full_empty(), "invariant"); |
238 assert(_free_list_mspace->is_full_empty(), "invariant"); |