-static bool stacktrace_add_method_intern(stacktracebuffer *stb,
- methodinfo *m,
- linenumbertable_entry *lntentry,
- ptrint lntsize,
- u1 *pc)
-{
- linenumbertable_entry *lntinline; /* special entry for inlined method */
-
- assert(stb);
- assert(lntentry);
-
- /* Find the line number for the specified PC (going backwards
- in the linenumber table). The linenumber table size is zero
- in native stubs. */
-
- for (; lntsize > 0; lntsize--, lntentry--) {
-
- /* did we reach the current line? */
- /* Note: In case of inlining this may actually compare the pc against a */
- /* methodinfo *, yielding a non-sensical result. This is no problem, */
- /* however, as we ignore such entries in the switch below. This way we */
- /* optimize for the common case (ie. a real pc in lntentry->pc). */
- if (pc >= lntentry->pc) {
-
- /* check for special inline entries */
- /* (see doc/inlining_stacktrace.txt for details */
- if ((s4)lntentry->line < 0) {
- switch (lntentry->line) {
- case -1:
- /* begin of inlined method (ie. INLINE_END instruction) */
-
- lntinline = --lntentry; /* get entry with methodinfo * */
- lntentry--; /* skip the special entry */
- lntsize -= 2;
-
- /* search inside the inlined method */
- if (stacktrace_add_method_intern(
- stb,
- (methodinfo*) lntinline->pc,
- lntentry,
- lntsize,
- pc))
- {
- /* the inlined method contained the pc */
- assert(lntinline->line <= -3);
- stacktrace_add_entry(stb, m, (-3) - lntinline->line);
- return true;
- }
- /* pc was not in inlined method, continue search. */
- /* Entries inside the inlined method will be skipped */
- /* because their lntentry->pc is higher than pc. */
- break;
-
- case -2:
- /* end of inlined method */
- return false;
-
- /* default: is only reached for an -3-line entry after a skipped */
- /* -2 entry. We can safely ignore it and continue searching. */
- }
- }
- else {
- /* found a normal entry */
- stacktrace_add_entry(stb, m, lntentry->line);
- return true;
- }