138 writer.inc_nof_strings(); |
138 writer.inc_nof_strings(); |
139 } |
139 } |
140 return current_epoch; |
140 return current_epoch; |
141 } |
141 } |
142 |
142 |
143 class StringPoolWriteOp { |
143 template <template <typename> class Operation> |
|
144 class StringPoolOp { |
144 public: |
145 public: |
145 typedef JfrStringPoolBuffer Type; |
146 typedef JfrStringPoolBuffer Type; |
146 private: |
147 private: |
147 UnBufferedWriteToChunk<Type> _writer; |
148 Operation<Type> _op; |
148 Thread* _thread; |
149 Thread* _thread; |
149 size_t _strings_processed; |
150 size_t _strings_processed; |
150 public: |
151 public: |
151 StringPoolWriteOp(JfrChunkWriter& writer, Thread* thread) : _writer(writer), _thread(thread), _strings_processed(0) {} |
152 StringPoolOp() : _op(), _thread(Thread::current()), _strings_processed(0) {} |
|
153 StringPoolOp(JfrChunkWriter& writer, Thread* thread) : _op(writer), _thread(thread), _strings_processed(0) {} |
152 bool write(Type* buffer, const u1* data, size_t size) { |
154 bool write(Type* buffer, const u1* data, size_t size) { |
153 buffer->acquire(_thread); // blocking |
155 assert(buffer->acquired_by(_thread) || buffer->retired(), "invariant"); |
154 const uint64_t nof_strings_used = buffer->string_count(); |
156 const uint64_t nof_strings_used = buffer->string_count(); |
155 assert(nof_strings_used > 0, "invariant"); |
157 assert(nof_strings_used > 0, "invariant"); |
156 buffer->set_string_top(buffer->string_top() + nof_strings_used); |
158 buffer->set_string_top(buffer->string_top() + nof_strings_used); |
157 // "size processed" for string pool buffers is the number of processed string elements |
159 // "size processed" for string pool buffers is the number of processed string elements |
158 _strings_processed += nof_strings_used; |
160 _strings_processed += nof_strings_used; |
159 const bool ret = _writer.write(buffer, data, size); |
161 return _op.write(buffer, data, size); |
160 buffer->release(); |
|
161 return ret; |
|
162 } |
162 } |
163 size_t processed() { return _strings_processed; } |
163 size_t processed() { return _strings_processed; } |
164 }; |
164 }; |
165 |
165 |
166 typedef StringPoolWriteOp WriteOperation; |
166 template <typename Type> |
167 typedef ConcurrentWriteOp<WriteOperation> ConcurrentWriteOperation; |
167 class StringPoolDiscarderStub { |
|
168 public: |
|
169 bool write(Type* buffer, const u1* data, size_t size) { |
|
170 // stub only, discard happens at higher level |
|
171 return true; |
|
172 } |
|
173 }; |
|
174 |
|
175 typedef StringPoolOp<UnBufferedWriteToChunk> WriteOperation; |
|
176 typedef StringPoolOp<StringPoolDiscarderStub> DiscardOperation; |
|
177 typedef ExclusiveOp<WriteOperation> ExclusiveWriteOperation; |
|
178 typedef ExclusiveOp<DiscardOperation> ExclusiveDiscardOperation; |
|
179 typedef ReleaseOp<JfrStringPoolMspace> StringPoolReleaseOperation; |
|
180 typedef CompositeOperation<ExclusiveWriteOperation, StringPoolReleaseOperation> StringPoolWriteOperation; |
|
181 typedef CompositeOperation<ExclusiveDiscardOperation, StringPoolReleaseOperation> StringPoolDiscardOperation; |
168 |
182 |
169 size_t JfrStringPool::write() { |
183 size_t JfrStringPool::write() { |
170 Thread* const thread = Thread::current(); |
184 Thread* const thread = Thread::current(); |
171 WriteOperation wo(_chunkwriter, thread); |
185 WriteOperation wo(_chunkwriter, thread); |
172 ConcurrentWriteOperation cwo(wo); |
186 ExclusiveWriteOperation ewo(wo); |
173 assert(_free_list_mspace->is_full_empty(), "invariant"); |
|
174 process_free_list(cwo, _free_list_mspace); |
|
175 return wo.processed(); |
|
176 } |
|
177 |
|
178 typedef MutexedWriteOp<WriteOperation> MutexedWriteOperation; |
|
179 typedef ReleaseOp<JfrStringPoolMspace> StringPoolReleaseOperation; |
|
180 typedef CompositeOperation<MutexedWriteOperation, StringPoolReleaseOperation> StringPoolWriteOperation; |
|
181 |
|
182 size_t JfrStringPool::write_at_safepoint() { |
|
183 assert(SafepointSynchronize::is_at_safepoint(), "invariant"); |
|
184 Thread* const thread = Thread::current(); |
|
185 WriteOperation wo(_chunkwriter, thread); |
|
186 MutexedWriteOperation mwo(wo); |
|
187 StringPoolReleaseOperation spro(_free_list_mspace, thread, false); |
187 StringPoolReleaseOperation spro(_free_list_mspace, thread, false); |
188 StringPoolWriteOperation spwo(&mwo, &spro); |
188 StringPoolWriteOperation spwo(&ewo, &spro); |
189 assert(_free_list_mspace->is_full_empty(), "invariant"); |
189 assert(_free_list_mspace->is_full_empty(), "invariant"); |
190 process_free_list(spwo, _free_list_mspace); |
190 process_free_list(spwo, _free_list_mspace); |
191 return wo.processed(); |
191 return wo.processed(); |
192 } |
192 } |
193 |
193 |
194 class StringPoolBufferDiscarder { |
194 size_t JfrStringPool::write_at_safepoint() { |
195 private: |
195 assert(SafepointSynchronize::is_at_safepoint(), "invariant"); |
196 Thread* _thread; |
196 return write(); |
197 size_t _processed; |
197 } |
198 public: |
|
199 typedef JfrStringPoolBuffer Type; |
|
200 StringPoolBufferDiscarder() : _thread(Thread::current()), _processed(0) {} |
|
201 bool process(Type* buffer) { |
|
202 buffer->acquire(_thread); // serialized access |
|
203 const u1* const current_top = buffer->top(); |
|
204 const size_t unflushed_size = buffer->pos() - current_top; |
|
205 if (unflushed_size == 0) { |
|
206 assert(buffer->string_count() == 0, "invariant"); |
|
207 buffer->release(); |
|
208 return true; |
|
209 } |
|
210 buffer->set_top(current_top + unflushed_size); |
|
211 const uint64_t nof_strings_used = buffer->string_count(); |
|
212 buffer->set_string_top(buffer->string_top() + nof_strings_used); |
|
213 // "size processed" for string pool buffers is the number of string elements |
|
214 _processed += (size_t)nof_strings_used; |
|
215 buffer->release(); |
|
216 return true; |
|
217 } |
|
218 size_t processed() const { return _processed; } |
|
219 }; |
|
220 |
198 |
221 size_t JfrStringPool::clear() { |
199 size_t JfrStringPool::clear() { |
222 StringPoolBufferDiscarder discard_operation; |
200 DiscardOperation discard_operation; |
|
201 ExclusiveDiscardOperation edo(discard_operation); |
|
202 StringPoolReleaseOperation spro(_free_list_mspace, Thread::current(), false); |
|
203 StringPoolDiscardOperation spdo(&edo, &spro); |
223 assert(_free_list_mspace->is_full_empty(), "invariant"); |
204 assert(_free_list_mspace->is_full_empty(), "invariant"); |
224 process_free_list(discard_operation, _free_list_mspace); |
205 process_free_list(spdo, _free_list_mspace); |
225 return discard_operation.processed(); |
206 return discard_operation.processed(); |
226 } |
207 } |
227 |
208 |
228 void JfrStringPool::register_full(BufferPtr t, Thread* thread) { |
209 void JfrStringPool::register_full(BufferPtr t, Thread* thread) { |
229 // nothing here at the moment |
210 // nothing here at the moment |
|
211 assert(t != NULL, "invariant"); |
|
212 assert(t->acquired_by(thread), "invariant"); |
230 assert(t->retired(), "invariant"); |
213 assert(t->retired(), "invariant"); |
231 } |
214 } |
232 |
215 |
233 void JfrStringPool::lock() { |
216 void JfrStringPool::lock() { |
234 assert(!_lock->owned_by_self(), "invariant"); |
217 assert(!_lock->owned_by_self(), "invariant"); |