--- /dev/null 2016-10-25 08:46:44.038854975 +0200
+++ new/src/share/vm/evtrace/traceStack.inline.hpp 2016-10-25 10:40:15.995782038 +0200
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ *
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at if you need additional information
+ * or have any questions.
+ *
+ * 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, see .
+ *
+ */
+
+#ifndef SHARE_VM_EVTRACE_TRACESTACK_INLINE_HPP
+#define SHARE_VM_EVTRACE_TRACESTACK_INLINE_HPP
+
+#include "runtime/vframe.hpp"
+#include "services/memTracker.hpp"
+
+//
+// TraceStackFrame
+//
+
+inline intptr_t TraceStackFrame::hash() const {
+ intptr_t h = 0;
+ if (is_compiled) {
+ h = (intptr_t) compiled.pc;
+ } else {
+ h = 31 * (intptr_t) interpreted.method + interpreted.bci;
+ }
+ h = 31 * h + (is_compiled ? 1 : 0);
+ return h;
+}
+
+inline bool TraceStackFrame::equals(const TraceStackFrame &other) const {
+ bool eql = false;
+ if (is_compiled == other.is_compiled) {
+ if (is_compiled) {
+ eql = (compiled.pc == other.compiled.pc);
+ assert(!eql || compiled.nm == other.compiled.nm, "sanity");
+ } else {
+ eql = (interpreted.method == other.interpreted.method && interpreted.bci == other.interpreted.bci);
+ }
+ }
+ return eql;
+}
+
+//
+// TraceStackBuilder
+//
+
+inline TraceStackBuilder::TraceStackBuilder() {
+ assert(EventTracingStackDepthLimit <= TRACE_STACK_MAX_FRAMES, "stack depth limit too high");
+ _hash = 0;
+ _count = 0;
+ _truncated = false;
+}
+
+inline const TraceStackFrame* TraceStackBuilder::frame_at(size_t index) const {
+ assert(index < _count, "range");
+ return &_frames[index];
+}
+
+//
+// CachedTraceStack
+//
+
+inline const TraceStackFrame *CachedTraceStack::frame_at(size_t index) const {
+ assert(index < _count, "range");
+ return &_frames[index];
+}
+
+inline void CachedTraceStack::invalidate() {
+ assert(_valid, "only once");
+ _valid = false;
+}
+
+inline CachedTraceStack *CachedTraceStack::cache_next() {
+ return _cache_next;
+}
+
+inline void CachedTraceStack::set_cache_next(CachedTraceStack *next) {
+ _cache_next = next;
+}
+
+//
+// CompositeTraceStack
+//
+
+inline CompositeTraceStack::CompositeTraceStack(TraceStackBuilder& top)
+: _top(top)
+{
+ set_bottom(NULL, 0);
+}
+
+inline const TraceStackFrame *CompositeTraceStack::frame_at(size_t index) const {
+ assert (index < count(), "range");
+ if (index < _top.count()) {
+ return _top.frame_at(index);
+ }
+ return _bottom->frame_at(index - _top.count() + _bottom_offset);
+}
+
+//
+// TraceStackVframeIterator
+//
+
+inline TraceStackVframeIterator::TraceStackVframeIterator(const CompositeTraceStack& ts)
+: _ts(ts)
+{
+ reset();
+}
+
+inline bool TraceStackVframeIterator::has_next() {
+ return (_index + 1 < (int)_ts.count() || _decode_offset != DebugInformationRecorder::serialized_null);
+}
+
+inline void TraceStackVframeIterator::fill_from_compiled_frame() {
+ assert(_decode_offset != DebugInformationRecorder::serialized_null, "sanity");
+
+ const TraceStackFrame *frame = _ts.frame_at(_index);
+ assert(frame->is_compiled, "sanity");
+
+ DebugInfoReadStream buffer(frame->compiled.nm, _decode_offset);
+ int sender_offset = buffer.read_int();
+ _method = buffer.read_method();
+ _bci = buffer.read_bci();
+
+ _decode_offset = sender_offset;
+}
+
+inline void TraceStackVframeIterator::next() {
+ assert(has_next(), "at end");
+ if (_decode_offset != DebugInformationRecorder::serialized_null) {
+ fill_from_compiled_frame();
+ } else {
+ _index++;
+ const TraceStackFrame *frame = _ts.frame_at(_index);
+ if (frame->is_compiled) {
+ nmethod *nm = frame->compiled.nm;
+ // Use pc_desc_near() because extra (non-safepoint) debug information is typically shared
+ // by several instructions and only emitted at the last instruction. Note that this COULD
+ // lead to wrong stack traces when there isn't any debug information for the current location
+ // and we pick up that of some other location which might even have different inlining.
+ // This should rarely occur and we have modified C1 and C2 so at least it shouldn't happen
+ // for monitorexit.
+ PcDesc *desc = nm->pc_desc_near(frame->compiled.pc);
+ if (!nm->is_native_method() && desc != NULL && desc->scope_decode_offset() != DebugInformationRecorder::serialized_null) {
+ _decode_offset = desc->scope_decode_offset();
+ fill_from_compiled_frame();
+ } else {
+ // Either this is a native method or we don't have a valid PcDesc. The latter can happen
+ // when the compiler did not emit debug information for the current location. This occurs
+ // for the instructions to exit the monitor in return and exception/unwind handlers of
+ // synchronized methods (which don't have an explicit monitorexit bytecode instruction).
+ // This does not seem to occur with inlined synchronized methods, so we just report the
+ // top-level method without a bci for this frame.
+ _method = nm->method();
+ _bci = 0;
+ _decode_offset = DebugInformationRecorder::serialized_null;
+ }
+ } else {
+ _method = frame->interpreted.method;
+ _bci = frame->interpreted.bci;
+ _decode_offset = DebugInformationRecorder::serialized_null;
+ }
+ }
+}
+
+inline void TraceStackVframeIterator::reset() {
+ _index = -1;
+ _decode_offset = DebugInformationRecorder::serialized_null;
+ _method = NULL;
+ _bci = -1;
+}
+
+#endif /* SHARE_VM_EVTRACE_TRACESTACK_INLINE_HPP */