src/share/vm/jfr/recorder/stringpool/jfrStringPool.cpp

changeset 9928
d2c2cd90513e
parent 9858
b985cbb00e68
equal deleted inserted replaced
9927:b273df69fbfe 9928:d2c2cd90513e
1 /* 1 /*
2 * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
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");

mercurial