src/hotspot/share/jfr/periodic/sampling/jfrCallTrace.cpp
author egahlin
Tue, 15 May 2018 20:24:34 +0200
changeset 50113 caf115bb98ad
child 51263 b5aac518b097
permissions -rw-r--r--
8199712: Flight Recorder Reviewed-by: coleenp, ihse, erikj, dsamersoff, mseledtsov, egahlin, mgronlun Contributed-by: erik.gahlin@oracle.com, markus.gronlund@oracle.com
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     1
/*
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     2
 * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     4
 *
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     7
 * published by the Free Software Foundation.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     8
 *
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    13
 * accompanied this code).
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    14
 *
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    18
 *
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    21
 * questions.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    22
 *
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    23
 */
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    24
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    25
#include "precompiled.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    26
#include "code/debugInfoRec.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    27
#include "code/nmethod.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    28
#include "code/pcDesc.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    29
#include "jfr/periodic/sampling/jfrCallTrace.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    30
#include "oops/method.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    31
#include "runtime/javaCalls.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    32
#include "runtime/frame.inline.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    33
#include "runtime/registerMap.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    34
#include "runtime/thread.inline.hpp"
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    35
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    36
bool JfrGetCallTrace::find_top_frame(frame& top_frame, Method** method, frame& first_frame) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    37
  assert(top_frame.cb() != NULL, "invariant");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    38
  RegisterMap map(_thread, false);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    39
  frame candidate = top_frame;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    40
  for (int i = 0; i < MaxJavaStackTraceDepth * 2; ++i) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    41
    if (candidate.is_entry_frame()) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    42
      JavaCallWrapper *jcw = candidate.entry_frame_call_wrapper_if_safe(_thread);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    43
      if (jcw == NULL || jcw->is_first_frame()) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    44
        return false;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    45
      }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    46
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    47
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    48
    if (candidate.is_interpreted_frame()) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    49
      JavaThreadState state = _thread->thread_state();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    50
      const bool known_valid = (state == _thread_in_native || state == _thread_in_vm || state == _thread_blocked);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    51
      if (known_valid || candidate.is_interpreted_frame_valid(_thread)) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    52
        Method* im = candidate.interpreter_frame_method();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    53
        if (known_valid && !im->is_valid_method()) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    54
          return false;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    55
        }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    56
        *method = im;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    57
        first_frame = candidate;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    58
        return true;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    59
      }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    60
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    61
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    62
    if (candidate.cb()->is_nmethod()) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    63
      // first check to make sure that we have a sane stack,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    64
      // the PC is actually inside the code part of the codeBlob,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    65
      // and we are past is_frame_complete_at (stack has been setup)
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    66
      if (!candidate.safe_for_sender(_thread)) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    67
        return false;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    68
      }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    69
      nmethod* nm = (nmethod*)candidate.cb();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    70
      *method = nm->method();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    71
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    72
      if (_in_java) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    73
        PcDesc* pc_desc = nm->pc_desc_near(candidate.pc() + 1);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    74
        if (pc_desc == NULL || pc_desc->scope_decode_offset() == DebugInformationRecorder::serialized_null) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    75
          return false;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    76
        }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    77
        candidate.set_pc(pc_desc->real_pc(nm));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    78
        assert(nm->pc_desc_at(candidate.pc()) != NULL, "invalid pc");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    79
      }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    80
      first_frame = candidate;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    81
      return true;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    82
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    83
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    84
    if (!candidate.safe_for_sender(_thread) ||
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    85
      candidate.is_stub_frame() ||
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    86
      candidate.cb()->frame_size() <= 0) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    87
      return false;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    88
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    89
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    90
    candidate = candidate.sender(&map);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    91
    if (candidate.cb() == NULL) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    92
      return false;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    93
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    94
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    95
  return false;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    96
}
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    97
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    98
bool JfrGetCallTrace::get_topframe(void* ucontext, frame& topframe) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    99
  if (!_thread->pd_get_top_frame_for_profiling(&topframe, ucontext, _in_java)) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   100
    return false;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   101
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   102
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   103
  if (topframe.cb() == NULL) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   104
    return false;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   105
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   106
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   107
  frame first_java_frame;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   108
  Method* method = NULL;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   109
  if (find_top_frame(topframe, &method, first_java_frame)) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   110
    if (method == NULL) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   111
      return false;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   112
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   113
    topframe = first_java_frame;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   114
    return true;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   115
  }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   116
  return false;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   117
}