# HG changeset patch # User dlong # Date 1545165387 28800 # Node ID 2f41e4935c34bc298dbfadf426b7ea5f8d4d7d60 # Parent 103ed9569fc8040395a49c50fff8c196bba690b8 8215205: javaVFrame much slower than vframeStream Reviewed-by: mchung, thartmann diff -r 103ed9569fc8 -r 2f41e4935c34 src/hotspot/share/code/scopeDesc.cpp --- a/src/hotspot/share/code/scopeDesc.cpp Tue Dec 18 12:08:51 2018 -0800 +++ b/src/hotspot/share/code/scopeDesc.cpp Tue Dec 18 12:36:27 2018 -0800 @@ -51,9 +51,9 @@ } -ScopeDesc::ScopeDesc(const ScopeDesc* parent) { +void ScopeDesc::initialize(const ScopeDesc* parent, int decode_offset) { _code = parent->_code; - _decode_offset = parent->_sender_decode_offset; + _decode_offset = decode_offset; _objects = parent->_objects; _reexecute = false; //reexecute only applies to the first scope _rethrow_exception = false; @@ -61,6 +61,14 @@ decode_body(); } +ScopeDesc::ScopeDesc(const ScopeDesc* parent) { + initialize(parent, parent->_sender_decode_offset); +} + +ScopeDesc::ScopeDesc(const ScopeDesc* parent, int decode_offset) { + initialize(parent, decode_offset); +} + void ScopeDesc::decode_body() { if (decode_offset() == DebugInformationRecorder::serialized_null) { diff -r 103ed9569fc8 -r 2f41e4935c34 src/hotspot/share/code/scopeDesc.hpp --- a/src/hotspot/share/code/scopeDesc.hpp Tue Dec 18 12:08:51 2018 -0800 +++ b/src/hotspot/share/code/scopeDesc.hpp Tue Dec 18 12:36:27 2018 -0800 @@ -67,6 +67,9 @@ // avoid a .hpp-.hpp dependency.) ScopeDesc(const CompiledMethod* code, int decode_offset, bool reexecute, bool rethrow_exception, bool return_oop); + // Direct access to scope + ScopeDesc* at_offset(int decode_offset) { return new ScopeDesc(this, decode_offset); } + // JVM state Method* method() const { return _method; } int bci() const { return _bci; } @@ -85,12 +88,16 @@ // Returns where the scope was decoded int decode_offset() const { return _decode_offset; } + int sender_decode_offset() const { return _sender_decode_offset; } + // Tells whether sender() returns NULL bool is_top() const; private: - // Alternative constructor + void initialize(const ScopeDesc* parent, int decode_offset); + // Alternative constructors ScopeDesc(const ScopeDesc* parent); + ScopeDesc(const ScopeDesc* parent, int decode_offset); // JVM state Method* _method; diff -r 103ed9569fc8 -r 2f41e4935c34 src/hotspot/share/runtime/vframe.cpp --- a/src/hotspot/share/runtime/vframe.cpp Tue Dec 18 12:08:51 2018 -0800 +++ b/src/hotspot/share/runtime/vframe.cpp Tue Dec 18 12:36:27 2018 -0800 @@ -452,8 +452,10 @@ _stop_at_java_call_stub = stop_at_java_call_stub; // skip top frame, as it may not be at safepoint + _prev_frame = top_frame; _frame = top_frame.sender(&_reg_map); while (!fill_from_frame()) { + _prev_frame = _frame; _frame = _frame.sender(&_reg_map); } } @@ -534,6 +536,37 @@ } } +javaVFrame* vframeStreamCommon::asJavaVFrame() { + javaVFrame* result = NULL; + if (_mode == compiled_mode) { + guarantee(_frame.is_compiled_frame(), "expected compiled Java frame"); + + // lazy update to register map + bool update_map = true; + RegisterMap map(_thread, update_map); + frame f = _prev_frame.sender(&map); + + guarantee(f.is_compiled_frame(), "expected compiled Java frame"); + + compiledVFrame* cvf = compiledVFrame::cast(vframe::new_vframe(&f, &map, _thread)); + + guarantee(cvf->cb() == cb(), "wrong code blob"); + + // get the same scope as this stream + cvf = cvf->at_scope(_decode_offset, _vframe_id); + + guarantee(cvf->scope()->decode_offset() == _decode_offset, "wrong scope"); + guarantee(cvf->scope()->sender_decode_offset() == _sender_decode_offset, "wrong scope"); + guarantee(cvf->vframe_id() == _vframe_id, "wrong vframe"); + + result = cvf; + } else { + result = javaVFrame::cast(vframe::new_vframe(&_frame, &_reg_map, _thread)); + } + guarantee(result->method() == method(), "wrong method"); + return result; +} + #ifndef PRODUCT void vframe::print() { diff -r 103ed9569fc8 -r 2f41e4935c34 src/hotspot/share/runtime/vframe.hpp --- a/src/hotspot/share/runtime/vframe.hpp Tue Dec 18 12:08:51 2018 -0800 +++ b/src/hotspot/share/runtime/vframe.hpp Tue Dec 18 12:36:27 2018 -0800 @@ -278,12 +278,16 @@ class vframeStreamCommon : StackObj { protected: // common + frame _prev_frame; frame _frame; JavaThread* _thread; RegisterMap _reg_map; enum { interpreted_mode, compiled_mode, at_end_mode } _mode; + // For compiled_mode + int _decode_offset; int _sender_decode_offset; + int _vframe_id; // Cached information Method* _method; @@ -320,6 +324,8 @@ return (CompiledMethod*) cb(); } + javaVFrame* asJavaVFrame(); + // Frame type inline bool is_interpreted_frame() const; inline bool is_entry_frame() const; diff -r 103ed9569fc8 -r 2f41e4935c34 src/hotspot/share/runtime/vframe.inline.hpp --- a/src/hotspot/share/runtime/vframe.inline.hpp Tue Dec 18 12:08:51 2018 -0800 +++ b/src/hotspot/share/runtime/vframe.inline.hpp Tue Dec 18 12:36:27 2018 -0800 @@ -44,6 +44,7 @@ // handle general case do { + _prev_frame = _frame; _frame = _frame.sender(&_reg_map); } while (!fill_from_frame()); } @@ -59,6 +60,7 @@ _frame = _thread->last_frame(); while (!fill_from_frame()) { + _prev_frame = _frame; _frame = _frame.sender(&_reg_map); } } @@ -68,12 +70,14 @@ 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 || @@ -118,6 +122,8 @@ 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; } @@ -187,6 +193,7 @@ decode_offset = pc_desc->scope_decode_offset(); } fill_from_compiled_frame(decode_offset); + _vframe_id = 0; } return true; } diff -r 103ed9569fc8 -r 2f41e4935c34 src/hotspot/share/runtime/vframe_hp.cpp --- a/src/hotspot/share/runtime/vframe_hp.cpp Tue Dec 18 12:08:51 2018 -0800 +++ b/src/hotspot/share/runtime/vframe_hp.cpp Tue Dec 18 12:36:27 2018 -0800 @@ -252,6 +252,14 @@ guarantee(_scope != NULL, "scope must be present"); } +compiledVFrame* compiledVFrame::at_scope(int decode_offset, int vframe_id) { + if (scope()->decode_offset() != decode_offset) { + ScopeDesc* scope = this->scope()->at_offset(decode_offset); + return new compiledVFrame(frame_pointer(), register_map(), thread(), scope, vframe_id); + } + assert(_vframe_id == vframe_id, "wrong frame id"); + return this; +} bool compiledVFrame::is_top() const { // FIX IT: Remove this when new native stubs are in place diff -r 103ed9569fc8 -r 2f41e4935c34 src/hotspot/share/runtime/vframe_hp.hpp --- a/src/hotspot/share/runtime/vframe_hp.hpp Tue Dec 18 12:08:51 2018 -0800 +++ b/src/hotspot/share/runtime/vframe_hp.hpp Tue Dec 18 12:36:27 2018 -0800 @@ -72,6 +72,9 @@ // Returns the scopeDesc ScopeDesc* scope() const { return _scope; } + // Return the compiledVFrame for the desired scope + compiledVFrame* at_scope(int decode_offset, int vframe_id); + // Returns SynchronizationEntryBCI or bci() (used for synchronization) int raw_bci() const;