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