Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  vframe.inline.hpp   Sprache: C

 
/*
 * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */


#ifndef SHARE_RUNTIME_VFRAME_INLINE_HPP
#define SHARE_RUNTIME_VFRAME_INLINE_HPP

#include "runtime/vframe.hpp"

#include "classfile/javaClasses.inline.hpp"
#include "oops/stackChunkOop.inline.hpp"
#include "runtime/continuationJavaClasses.inline.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/javaThread.inline.hpp"

inline vframeStreamCommon::vframeStreamCommon(RegisterMap reg_map) : _reg_map(reg_map), _cont_entry(NULL) {
  _thread = _reg_map.thread();
}

inline oop vframeStreamCommon::continuation() const {
  if (_reg_map.cont() != NULL) {
    return _reg_map.cont();
  } else if (_cont_entry != NULL) {
    return _cont_entry->cont_oop(_reg_map.thread());
  } else {
    return NULL;
  }
}

inline intptr_t* vframeStreamCommon::frame_id() const {
  if (_frame.is_heap_frame()) {
    // Make something sufficiently unique
    intptr_t id = _reg_map.stack_chunk_index() << 16;
    id += _frame.offset_unextended_sp();
    return reinterpret_cast<intptr_t*>(id);
  }
  return _frame.id();
}

inline int vframeStreamCommon::vframe_id() const {
  assert(_mode == compiled_mode, "unexpected mode: %d", _mode);
  return _vframe_id;
}

inline int vframeStreamCommon::decode_offset() const {
  assert(_mode == compiled_mode, "unexpected mode: %d", _mode);
  return _decode_offset;
}

inline bool vframeStreamCommon::is_interpreted_frame() const { return _frame.is_interpreted_frame(); }

inline void vframeStreamCommon::next() {
  // handle frames with inlining
  if (_mode == compiled_mode    && fill_in_compiled_inlined_sender()) return;

  // handle general case
  do {
    bool is_enterSpecial_frame  = false;
    if (Continuation::is_continuation_enterSpecial(_frame)) {
      assert(!_reg_map.in_cont(), "");
      assert(_cont_entry != NULL, "");
      // Reading oops are only safe if process_frames() is true, and we fix the oops.
      assert(!_reg_map.process_frames() || _cont_entry->cont_oop(_reg_map.thread()) != NULL"_cont: " INTPTR_FORMAT, p2i(_cont_entry));
      is_enterSpecial_frame = true;

      // TODO: handle ShowCarrierFrames
      if (_cont_entry->is_virtual_thread() ||
          (_continuation_scope.not_null() && _cont_entry->scope(_reg_map.thread()) == _continuation_scope())) {
        _mode = at_end_mode;
        break;
      }
    } else if (_reg_map.in_cont() && Continuation::is_continuation_entry_frame(_frame, &_reg_map)) {
      assert(_reg_map.cont() != NULL, "");
      oop scope = jdk_internal_vm_Continuation::scope(_reg_map.cont());
      if (scope == java_lang_VirtualThread::vthread_scope() ||
          (_continuation_scope.not_null() && scope == _continuation_scope())) {
        _mode = at_end_mode;
        break;
      }
    }

    _frame = _frame.sender(&_reg_map);

    if (is_enterSpecial_frame) {
      _cont_entry = _cont_entry->parent();
    }
  } while (!fill_from_frame());
}

inline vframeStream::vframeStream(JavaThread* thread, bool stop_at_java_call_stub, bool process_frame, bool vthread_carrier)
  : vframeStreamCommon(RegisterMap(thread,
                                   RegisterMap::UpdateMap::include,
                                   process_frame ? RegisterMap::ProcessFrames::include : RegisterMap::ProcessFrames::skip ,
                                   RegisterMap::WalkContinuation::include)) {
  _stop_at_java_call_stub = stop_at_java_call_stub;

  if (!thread->has_last_Java_frame()) {
    _mode = at_end_mode;
    return;
  }

  if (thread->is_vthread_mounted()) {
    _frame = vthread_carrier ? _thread->carrier_last_frame(&_reg_map) : _thread->vthread_last_frame();
  } else {
    _frame = _thread->last_frame();
  }

  _cont_entry = _thread->last_continuation();
  while (!fill_from_frame()) {
    _frame = _frame.sender(&_reg_map);
  }
}

inline bool vframeStreamCommon::fill_in_compiled_inlined_sender() {
  if (_sender_decode_offset == DebugInformationRecorder::serialized_null) {
    return false;
  }
  fill_from_compiled_frame(_sender_decode_offset);
  ++_vframe_id;
  return true;
}


inline void vframeStreamCommon::fill_from_compiled_frame(int decode_offset) {
  _mode = compiled_mode;
  _decode_offset = decode_offset;

  // Range check to detect ridiculous offsets.
  if (decode_offset == DebugInformationRecorder::serialized_null ||
      decode_offset < 0 ||
      decode_offset >= nm()->scopes_data_size()) {
    // 6379830 AsyncGetCallTrace sometimes feeds us wild frames.
    // If we read nmethod::scopes_data at serialized_null (== 0)
    // or if read some at other invalid offset, invalid values will be decoded.
    // Based on these values, invalid heap locations could be referenced
    // that could lead to crashes in product mode.
    // Therefore, do not use the decode offset if invalid, but fill the frame
    // as it were a native compiled frame (no Java-level assumptions).
#ifdef ASSERT
    if (WizardMode) {
      ttyLocker ttyl;
      tty->print_cr("Error in fill_from_frame: pc_desc for "
                    INTPTR_FORMAT " not found or invalid at %d",
                    p2i(_frame.pc()), decode_offset);
      nm()->print();
      nm()->method()->print_codes();
      nm()->print_code();
      nm()->print_pcs();
    }
    found_bad_method_frame();
#endif
    // Provide a cheap fallback in product mode.  (See comment above.)
    fill_from_compiled_native_frame();
    return;
  }

  // Decode first part of scopeDesc
  DebugInfoReadStream buffer(nm(), decode_offset);
  _sender_decode_offset = buffer.read_int();
  _method               = buffer.read_method();
  _bci                  = buffer.read_bci();

  assert(_method->is_method(), "checking type of decoded method");
}

// The native frames are handled specially. We do not rely on ScopeDesc info
// since the pc might not be exact due to the _last_native_pc trick.
inline void vframeStreamCommon::fill_from_compiled_native_frame() {
  _mode = compiled_mode;
  _sender_decode_offset = DebugInformationRecorder::serialized_null;
  _decode_offset = DebugInformationRecorder::serialized_null;
  _vframe_id = 0;
  _method = nm()->method();
  _bci = 0;
}

inline bool vframeStreamCommon::fill_from_frame() {
  // Interpreted frame
  if (_frame.is_interpreted_frame()) {
    fill_from_interpreter_frame();
    return true;
  }

  // Compiled frame

  if (cb() != NULL && cb()->is_compiled()) {
    assert(nm()->method() != NULL, "must be");
    if (nm()->is_native_method()) {
      // Do not rely on scopeDesc since the pc might be imprecise due to the _last_native_pc trick.
      fill_from_compiled_native_frame();
    } else {
      PcDesc* pc_desc = nm()->pc_desc_at(_frame.pc());
      int decode_offset;
      if (pc_desc == NULL) {
        // Should not happen, but let fill_from_compiled_frame handle it.

        // If we are trying to walk the stack of a thread that is not
        // at a safepoint (like AsyncGetCallTrace would do) then this is an
        // acceptable result. [ This is assuming that safe_for_sender
        // is so bullet proof that we can trust the frames it produced. ]
        //
        // So if we see that the thread is not safepoint safe
        // then simply produce the method and a bci of zero
        // and skip the possibility of decoding any inlining that
        // may be present. That is far better than simply stopping (or
        // asserting. If however the thread is safepoint safe this
        // is the sign of a compiler bug  and we'll let
        // fill_from_compiled_frame handle it.


        JavaThreadState state = _thread != NULL ? _thread->thread_state() : _thread_in_Java;

        // in_Java should be good enough to test safepoint safety
        // if state were say in_Java_trans then we'd expect that
        // the pc would have already been slightly adjusted to
        // one that would produce a pcDesc since the trans state
        // would be one that might in fact anticipate a safepoint

        if (state == _thread_in_Java ) {
          // This will get a method a zero bci and no inlining.
          // Might be nice to have a unique bci to signify this
          // particular case but for now zero will do.

          fill_from_compiled_native_frame();

          // There is something to be said for setting the mode to
          // at_end_mode to prevent trying to walk further up the
          // stack. There is evidence that if we walk any further
          // that we could produce a bad stack chain. However until
          // we see evidence that allowing this causes us to find
          // frames bad enough to cause segv's or assertion failures
          // we don't do it as while we may get a bad call chain the
          // probability is much higher (several magnitudes) that we
          // get good data.

          return true;
        }
        decode_offset = DebugInformationRecorder::serialized_null;
      } else {
        decode_offset = pc_desc->scope_decode_offset();
      }
      fill_from_compiled_frame(decode_offset);

      _vframe_id = 0;
    }
    return true;
  }

  // End of stack?
  if (_frame.is_first_frame() || (_stop_at_java_call_stub && _frame.is_entry_frame())) {
    _mode = at_end_mode;
    return true;
  }

  assert(!Continuation::is_continuation_enterSpecial(_frame), "");
  return false;
}


inline void vframeStreamCommon::fill_from_interpreter_frame() {
  Method* method;
  address bcp;
  if (!_reg_map.in_cont()) {
    method = _frame.interpreter_frame_method();
    bcp    = _frame.interpreter_frame_bcp();
  } else {
    method = _reg_map.stack_chunk()->interpreter_frame_method(_frame);
    bcp    = _reg_map.stack_chunk()->interpreter_frame_bcp(_frame);
  }
  int bci  = method->validate_bci_from_bcp(bcp);
  // 6379830 AsyncGetCallTrace sometimes feeds us wild frames.
  // AsyncGetCallTrace interrupts the VM asynchronously. As a result
  // it is possible to access an interpreter frame for which
  // no Java-level information is yet available (e.g., because
  // the frame was being created when the VM interrupted it).
  // In this scenario, pretend that the interpreter is at the point
  // of entering the method.
  if (bci < 0) {
    DEBUG_ONLY(found_bad_method_frame();)
    bci = 0;
  }
  _mode   = interpreted_mode;
  _method = method;
  _bci    = bci;
}

#endif // SHARE_RUNTIME_VFRAME_INLINE_HPP

94%


¤ Dauer der Verarbeitung: 0.7 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge