147 const StackTrace* table_entry = _table[index];
148
149 while (table_entry != NULL) {
150 if (table_entry->equals(stacktrace)) {
151 return table_entry->id();
152 }
153 table_entry = table_entry->next();
154 }
155
156 if (!stacktrace.have_lineno()) {
157 return 0;
158 }
159
160 traceid id = ++_next_id;
161 _table[index] = new StackTrace(id, stacktrace, _table[index]);
162 ++_entries;
163 return id;
164 }
165
166 traceid JfrStackTraceRepository::add(const JfrStackTrace& stacktrace) {
167 return instance().add_trace(stacktrace);
168 }
169
170 traceid JfrStackTraceRepository::record(Thread* thread, int skip /* 0 */) {
171 assert(thread == Thread::current(), "invariant");
172 JfrThreadLocal* const tl = thread->jfr_thread_local();
173 assert(tl != NULL, "invariant");
174 if (tl->has_cached_stack_trace()) {
175 return tl->cached_stack_trace_id();
176 }
177 if (!thread->is_Java_thread() || thread->is_hidden_from_external_view()) {
178 return 0;
179 }
180 JfrStackFrame* frames = tl->stackframes();
181 if (frames == NULL) {
182 // pending oom
183 return 0;
184 }
185 assert(frames != NULL, "invariant");
186 assert(tl->stackframes() == frames, "invariant");
187 return instance().record_for((JavaThread*)thread, skip,frames, tl->stackdepth());
188 }
189
190 traceid JfrStackTraceRepository::record(Thread* thread, int skip, unsigned int* hash) {
191 assert(thread == Thread::current(), "invariant");
192 JfrThreadLocal* const tl = thread->jfr_thread_local();
193 assert(tl != NULL, "invariant");
194
195 if (tl->has_cached_stack_trace()) {
196 *hash = tl->cached_stack_trace_hash();
197 return tl->cached_stack_trace_id();
198 }
199 if (!thread->is_Java_thread() || thread->is_hidden_from_external_view()) {
200 return 0;
201 }
202 JfrStackFrame* frames = tl->stackframes();
203 if (frames == NULL) {
204 // pending oom
205 return 0;
206 }
207 assert(frames != NULL, "invariant");
208 assert(tl->stackframes() == frames, "invariant");
209 return instance().record_for((JavaThread*)thread, skip, frames, tl->stackdepth(), hash);
210 }
211
212 traceid JfrStackTraceRepository::record_for(JavaThread* thread, int skip, JfrStackFrame *frames, u4 max_frames) {
213 JfrStackTrace stacktrace(frames, max_frames);
214 if (!stacktrace.record_safe(thread, skip)) {
215 return 0;
216 }
217 traceid tid = add(stacktrace);
218 if (tid == 0) {
219 stacktrace.resolve_linenos();
220 tid = add(stacktrace);
221 }
222 return tid;
223 }
224
225 traceid JfrStackTraceRepository::record_for(JavaThread* thread, int skip, JfrStackFrame *frames, u4 max_frames, unsigned int* hash) {
226 assert(hash != NULL && *hash == 0, "invariant");
227 JfrStackTrace stacktrace(frames, max_frames);
228 if (!stacktrace.record_safe(thread, skip, true)) {
229 return 0;
230 }
231 traceid tid = add(stacktrace);
232 if (tid == 0) {
233 stacktrace.resolve_linenos();
234 tid = add(stacktrace);
235 }
236 *hash = stacktrace._hash;
237 return tid;
238 }
239
240 size_t JfrStackTraceRepository::write_impl(JfrChunkWriter& sw, bool clear) {
241 MutexLockerEx lock(JfrStacktrace_lock, Mutex::_no_safepoint_check_flag);
242 assert(_entries > 0, "invariant");
243 int count = 0;
244 for (u4 i = 0; i < TABLE_SIZE; ++i) {
245 JfrStackTraceRepository::StackTrace* stacktrace = _table[i];
246 while (stacktrace != NULL) {
247 JfrStackTraceRepository::StackTrace* next = stacktrace->next();
248 if (stacktrace->should_write()) {
249 stacktrace->write(sw);
250 ++count;
251 }
252 if (clear) {
253 delete stacktrace;
254 }
255 stacktrace = next;
256 }
257 }
346 write_frame(cw, _methodid, _line, _bci, _type);
347 }
348
349 void JfrStackFrame::write(JfrCheckpointWriter& cpw) const {
350 write_frame(cpw, _methodid, _line, _bci, _type);
351 }
352
353 // invariant is that the entry to be resolved actually exists in the table
354 const JfrStackTraceRepository::StackTrace* JfrStackTraceRepository::resolve_entry(unsigned int hash, traceid id) const {
355 const size_t index = (hash % TABLE_SIZE);
356 const StackTrace* trace = _table[index];
357 while (trace != NULL && trace->id() != id) {
358 trace = trace->next();
359 }
360 assert(trace != NULL, "invariant");
361 assert(trace->hash() == hash, "invariant");
362 assert(trace->id() == id, "invariant");
363 return trace;
364 }
365
366 void JfrStackFrame::resolve_lineno() {
367 assert(_method, "no method pointer");
368 assert(_line == 0, "already have linenumber");
369 _line = _method->line_number_from_bci(_bci);
370 _method = NULL;
371 }
372
373 void JfrStackTrace::set_frame(u4 frame_pos, JfrStackFrame& frame) {
374 assert(frame_pos < _max_frames, "illegal frame_pos");
375 _frames[frame_pos] = frame;
376 }
377
378 void JfrStackTrace::resolve_linenos() {
379 for(unsigned int i = 0; i < _nr_of_frames; i++) {
380 _frames[i].resolve_lineno();
381 }
382 _lineno = true;
383 }
384
385 bool JfrStackTrace::record_safe(JavaThread* thread, int skip, bool leakp /* false */) {
386 assert(SafepointSynchronize::safepoint_safe(thread, thread->thread_state())
387 || thread == Thread::current(), "Thread stack needs to be walkable");
388 vframeStream vfs(thread);
389 u4 count = 0;
390 _reached_root = true;
391 for(int i = 0; i < skip; i++) {
392 if (vfs.at_end()) {
393 break;
394 }
395 vfs.next();
396 }
397
398 while (!vfs.at_end()) {
|
147 const StackTrace* table_entry = _table[index];
148
149 while (table_entry != NULL) {
150 if (table_entry->equals(stacktrace)) {
151 return table_entry->id();
152 }
153 table_entry = table_entry->next();
154 }
155
156 if (!stacktrace.have_lineno()) {
157 return 0;
158 }
159
160 traceid id = ++_next_id;
161 _table[index] = new StackTrace(id, stacktrace, _table[index]);
162 ++_entries;
163 return id;
164 }
165
166 traceid JfrStackTraceRepository::add(const JfrStackTrace& stacktrace) {
167 traceid tid = instance().add_trace(stacktrace);
168 if (tid == 0) {
169 stacktrace.resolve_linenos();
170 tid = instance().add_trace(stacktrace);
171 }
172 assert(tid != 0, "invariant");
173 return tid;
174 }
175
176 traceid JfrStackTraceRepository::record(Thread* thread, int skip /* 0 */) {
177 assert(thread == Thread::current(), "invariant");
178 JfrThreadLocal* const tl = thread->jfr_thread_local();
179 assert(tl != NULL, "invariant");
180 if (tl->has_cached_stack_trace()) {
181 return tl->cached_stack_trace_id();
182 }
183 if (!thread->is_Java_thread() || thread->is_hidden_from_external_view()) {
184 return 0;
185 }
186 JfrStackFrame* frames = tl->stackframes();
187 if (frames == NULL) {
188 // pending oom
189 return 0;
190 }
191 assert(frames != NULL, "invariant");
192 assert(tl->stackframes() == frames, "invariant");
193 return instance().record_for((JavaThread*)thread, skip,frames, tl->stackdepth());
194 }
195
196 traceid JfrStackTraceRepository::record_for(JavaThread* thread, int skip, JfrStackFrame *frames, u4 max_frames) {
197 JfrStackTrace stacktrace(frames, max_frames);
198 return stacktrace.record_safe(thread, skip) ? add(stacktrace) : 0;
199 }
200
201 traceid JfrStackTraceRepository::add(const JfrStackTrace* stacktrace, JavaThread* thread) {
202 assert(stacktrace != NULL, "invariant");
203 assert(thread != NULL, "invariant");
204 assert(stacktrace->hash() != 0, "invariant");
205 return add(*stacktrace);
206 }
207
208 bool JfrStackTraceRepository::fill_stacktrace_for(JavaThread* thread, JfrStackTrace* stacktrace, int skip) {
209 assert(thread == Thread::current(), "invariant");
210 assert(stacktrace != NULL, "invariant");
211 JfrThreadLocal* const tl = thread->jfr_thread_local();
212 assert(tl != NULL, "invariant");
213 const unsigned int cached_stacktrace_hash = tl->cached_stack_trace_hash();
214 if (cached_stacktrace_hash != 0) {
215 stacktrace->set_hash(cached_stacktrace_hash);
216 return true;
217 }
218 return stacktrace->record_safe(thread, skip, true);
219 }
220
221 size_t JfrStackTraceRepository::write_impl(JfrChunkWriter& sw, bool clear) {
222 MutexLockerEx lock(JfrStacktrace_lock, Mutex::_no_safepoint_check_flag);
223 assert(_entries > 0, "invariant");
224 int count = 0;
225 for (u4 i = 0; i < TABLE_SIZE; ++i) {
226 JfrStackTraceRepository::StackTrace* stacktrace = _table[i];
227 while (stacktrace != NULL) {
228 JfrStackTraceRepository::StackTrace* next = stacktrace->next();
229 if (stacktrace->should_write()) {
230 stacktrace->write(sw);
231 ++count;
232 }
233 if (clear) {
234 delete stacktrace;
235 }
236 stacktrace = next;
237 }
238 }
327 write_frame(cw, _methodid, _line, _bci, _type);
328 }
329
330 void JfrStackFrame::write(JfrCheckpointWriter& cpw) const {
331 write_frame(cpw, _methodid, _line, _bci, _type);
332 }
333
334 // invariant is that the entry to be resolved actually exists in the table
335 const JfrStackTraceRepository::StackTrace* JfrStackTraceRepository::resolve_entry(unsigned int hash, traceid id) const {
336 const size_t index = (hash % TABLE_SIZE);
337 const StackTrace* trace = _table[index];
338 while (trace != NULL && trace->id() != id) {
339 trace = trace->next();
340 }
341 assert(trace != NULL, "invariant");
342 assert(trace->hash() == hash, "invariant");
343 assert(trace->id() == id, "invariant");
344 return trace;
345 }
346
347 void JfrStackFrame::resolve_lineno() const {
348 assert(_method, "no method pointer");
349 assert(_line == 0, "already have linenumber");
350 _line = _method->line_number_from_bci(_bci);
351 _method = NULL;
352 }
353
354 void JfrStackTrace::set_frame(u4 frame_pos, JfrStackFrame& frame) {
355 assert(frame_pos < _max_frames, "illegal frame_pos");
356 _frames[frame_pos] = frame;
357 }
358
359 void JfrStackTrace::resolve_linenos() const {
360 for(unsigned int i = 0; i < _nr_of_frames; i++) {
361 _frames[i].resolve_lineno();
362 }
363 _lineno = true;
364 }
365
366 bool JfrStackTrace::record_safe(JavaThread* thread, int skip, bool leakp /* false */) {
367 assert(SafepointSynchronize::safepoint_safe(thread, thread->thread_state())
368 || thread == Thread::current(), "Thread stack needs to be walkable");
369 vframeStream vfs(thread);
370 u4 count = 0;
371 _reached_root = true;
372 for(int i = 0; i < skip; i++) {
373 if (vfs.at_end()) {
374 break;
375 }
376 vfs.next();
377 }
378
379 while (!vfs.at_end()) {
|