2323#include < string.h>
2424#include < sys/syscall.h>
2525
26+ #include " counters.h"
27+ #include " tsc.h"
28+
2629#ifdef __APPLE__
2730#define REG (l, m ) _ucontext->uc_mcontext->__ss.__##m
2831#else
@@ -57,6 +60,7 @@ void StackFrame::ret() { pc() = link(); }
5760
5861bool StackFrame::unwindStub (instruction_t *entry, const char *name,
5962 uintptr_t &pc, uintptr_t &sp, uintptr_t &fp) {
63+ const u64 startTime = TSC::ticks ();
6064 instruction_t *ip = (instruction_t *)pc;
6165 if (ip == entry || *ip == 0xd65f03c0 || strncmp (name, " itable" , 6 ) == 0 ||
6266 strncmp (name, " vtable" , 6 ) == 0 ||
@@ -67,6 +71,12 @@ bool StackFrame::unwindStub(instruction_t *entry, const char *name,
6771 strcmp (name, " atomic entry points" ) == 0 ||
6872 strcmp (name, " InlineCacheBuffer" ) == 0 ) {
6973 pc = link ();
74+
75+ const u64 endTime = TSC::ticks ();
76+ const u64 duration = TSC::ticks_to_millis (endTime - startTime);
77+ if (duration > 1 ) {
78+ Counters::increment (UNWINDING_STUB_TIME, duration);
79+ }
7080 return true ;
7181 } else if (strcmp (name, " forward_copy_longs" ) == 0 ||
7282 strcmp (name, " backward_copy_longs" ) == 0
@@ -83,6 +93,12 @@ bool StackFrame::unwindStub(instruction_t *entry, const char *name,
8393 // When cstack=vm, unwind stub frames one by one
8494 pc = link ();
8595 }
96+
97+ const u64 endTime = TSC::ticks ();
98+ const u64 duration = TSC::ticks_to_millis (endTime - startTime);
99+ if (duration > 1 ) {
100+ Counters::increment (UNWINDING_STUB_TIME, duration);
101+ }
86102 return true ;
87103 } else if (entry != NULL && entry[0 ] == 0xa9bf7bfd ) {
88104 // The stub begins with
@@ -91,11 +107,23 @@ bool StackFrame::unwindStub(instruction_t *entry, const char *name,
91107 if (ip == entry + 1 ) {
92108 sp += 16 ;
93109 pc = ((uintptr_t *)sp)[-1 ];
110+
111+ const u64 endTime = TSC::ticks ();
112+ const u64 duration = TSC::ticks_to_millis (endTime - startTime);
113+ if (duration > 1 ) {
114+ Counters::increment (UNWINDING_STUB_TIME, duration);
115+ }
94116 return true ;
95117 } else if (entry[1 ] == 0x910003fd && withinCurrentStack (fp)) {
96118 sp = fp + 16 ;
97119 fp = ((uintptr_t *)sp)[-2 ];
98120 pc = ((uintptr_t *)sp)[-1 ];
121+
122+ const u64 endTime = TSC::ticks ();
123+ const u64 duration = TSC::ticks_to_millis (endTime - startTime);
124+ if (duration > 1 ) {
125+ Counters::increment (UNWINDING_STUB_TIME, duration);
126+ }
99127 return true ;
100128 }
101129 } else if (strncmp (name, " indexof_linear_" , 15 ) == 0 &&
@@ -104,8 +132,20 @@ bool StackFrame::unwindStub(instruction_t *entry, const char *name,
104132 // Entry and exit are covered by the very first 'if', in all other cases SP is 4 words off.
105133 sp += 32 ;
106134 pc = link ();
107- return true ;
135+
136+ const u64 endTime = TSC::ticks ();
137+ const u64 duration = TSC::ticks_to_millis (endTime - startTime);
138+ if (duration > 1 ) {
139+ Counters::increment (UNWINDING_STUB_TIME, duration);
140+ }
141+ return true ;
108142 }
143+
144+ const u64 endTime = TSC::ticks ();
145+ const u64 duration = TSC::ticks_to_millis (endTime - startTime);
146+ if (duration > 1 ) {
147+ Counters::increment (UNWINDING_STUB_TIME, duration);
148+ }
109149 return false ;
110150}
111151
@@ -117,6 +157,7 @@ static inline bool isEntryBarrier(instruction_t *ip) {
117157
118158bool StackFrame::unwindCompiled (NMethod *nm, uintptr_t &pc, uintptr_t &sp,
119159 uintptr_t &fp) {
160+ const u64 startTime = TSC::ticks ();
120161 instruction_t *ip = (instruction_t *)pc;
121162 instruction_t *entry = (instruction_t *)nm->entry ();
122163 if ((*ip & 0xffe07fff ) == 0xa9007bfd ) {
@@ -125,34 +166,71 @@ bool StackFrame::unwindCompiled(NMethod *nm, uintptr_t &pc, uintptr_t &sp,
125166 unsigned int offset = (*ip >> 12 ) & 0x1f8 ;
126167 sp += offset + 16 ;
127168 pc = link ();
169+
170+ const u64 endTime = TSC::ticks ();
171+ const u64 duration = TSC::ticks_to_millis (endTime - startTime);
172+ if (duration > 1 ) {
173+ Counters::increment (UNWINDING_STUB_TIME, duration);
174+ }
128175 } else if (ip > entry && ip[0 ] == 0x910003fd && ip[-1 ] == 0xa9bf7bfd ) {
129176 // stp x29, x30, [sp, #-16]!
130177 // mov x29, sp
131178 sp += 16 ;
132179 pc = ((uintptr_t *)sp)[-1 ];
180+
181+ const u64 endTime = TSC::ticks ();
182+ const u64 duration = TSC::ticks_to_millis (endTime - startTime);
183+ if (duration > 1 ) {
184+ Counters::increment (UNWINDING_STUB_TIME, duration);
185+ }
133186 } else if (ip > entry + 3 && !nm->isFrameCompleteAt (ip) &&
134187 (isEntryBarrier (ip) || isEntryBarrier (ip + 1 ))) {
135188 // Frame should be complete at this point
136189 sp += nm->frameSize () * sizeof (void *);
137190 fp = ((uintptr_t *)sp)[-2 ];
138191 pc = ((uintptr_t *)sp)[-1 ];
192+
193+ const u64 endTime = TSC::ticks ();
194+ const u64 duration = TSC::ticks_to_millis (endTime - startTime);
195+ if (duration > 1 ) {
196+ Counters::increment (UNWINDING_STUB_TIME, duration);
197+ }
139198 } else {
140199 // Just try
141200 pc = link ();
142201 }
202+
203+ const u64 endTime = TSC::ticks ();
204+ const u64 duration = TSC::ticks_to_millis (endTime - startTime);
205+ if (duration > 1 ) {
206+ Counters::increment (UNWINDING_STUB_TIME, duration);
207+ }
143208 return true ;
144209}
145210
146211bool StackFrame::unwindAtomicStub (const void *& pc) {
147212 // VM threads may call generated atomic stubs, which are not normally walkable
213+ const u64 startTime = TSC::ticks ();
148214 const void * lr = (const void *)link ();
149215 if (VMStructs::libjvm ()->contains (lr)) {
150216 NMethod* nm = CodeHeap::findNMethod (pc);
151217 if (nm != NULL && strncmp (nm->name (), " Stub" , 4 ) == 0 ) {
152218 pc = lr;
219+
220+ const u64 endTime = TSC::ticks ();
221+ const u64 duration = TSC::ticks_to_millis (endTime - startTime);
222+ if (duration > 1 ) {
223+ Counters::increment (UNWINDING_STUB_TIME, duration);
224+ }
153225 return true ;
154226 }
155227 }
228+
229+ const u64 endTime = TSC::ticks ();
230+ const u64 duration = TSC::ticks_to_millis (endTime - startTime);
231+ if (duration > 1 ) {
232+ Counters::increment (UNWINDING_STUB_TIME, duration);
233+ }
156234 return false ;
157235}
158236
0 commit comments