--- /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 */