8215205: javaVFrame much slower than vframeStream

Reviewed-by: mchung, thartmann
This commit is contained in:
Dean Long 2018-12-18 12:36:27 -08:00
parent 84105b36fd
commit 32ea2e5343
7 changed files with 75 additions and 3 deletions

View file

@ -51,9 +51,9 @@ ScopeDesc::ScopeDesc(const CompiledMethod* code, int decode_offset, bool reexecu
} }
ScopeDesc::ScopeDesc(const ScopeDesc* parent) { void ScopeDesc::initialize(const ScopeDesc* parent, int decode_offset) {
_code = parent->_code; _code = parent->_code;
_decode_offset = parent->_sender_decode_offset; _decode_offset = decode_offset;
_objects = parent->_objects; _objects = parent->_objects;
_reexecute = false; //reexecute only applies to the first scope _reexecute = false; //reexecute only applies to the first scope
_rethrow_exception = false; _rethrow_exception = false;
@ -61,6 +61,14 @@ ScopeDesc::ScopeDesc(const ScopeDesc* parent) {
decode_body(); 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() { void ScopeDesc::decode_body() {
if (decode_offset() == DebugInformationRecorder::serialized_null) { if (decode_offset() == DebugInformationRecorder::serialized_null) {

View file

@ -67,6 +67,9 @@ class ScopeDesc : public ResourceObj {
// avoid a .hpp-.hpp dependency.) // avoid a .hpp-.hpp dependency.)
ScopeDesc(const CompiledMethod* code, int decode_offset, bool reexecute, bool rethrow_exception, bool return_oop); 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 // JVM state
Method* method() const { return _method; } Method* method() const { return _method; }
int bci() const { return _bci; } int bci() const { return _bci; }
@ -85,12 +88,16 @@ class ScopeDesc : public ResourceObj {
// Returns where the scope was decoded // Returns where the scope was decoded
int decode_offset() const { return _decode_offset; } int decode_offset() const { return _decode_offset; }
int sender_decode_offset() const { return _sender_decode_offset; }
// Tells whether sender() returns NULL // Tells whether sender() returns NULL
bool is_top() const; bool is_top() const;
private: private:
// Alternative constructor void initialize(const ScopeDesc* parent, int decode_offset);
// Alternative constructors
ScopeDesc(const ScopeDesc* parent); ScopeDesc(const ScopeDesc* parent);
ScopeDesc(const ScopeDesc* parent, int decode_offset);
// JVM state // JVM state
Method* _method; Method* _method;

View file

@ -452,8 +452,10 @@ vframeStream::vframeStream(JavaThread* thread, frame top_frame,
_stop_at_java_call_stub = stop_at_java_call_stub; _stop_at_java_call_stub = stop_at_java_call_stub;
// skip top frame, as it may not be at safepoint // skip top frame, as it may not be at safepoint
_prev_frame = top_frame;
_frame = top_frame.sender(&_reg_map); _frame = top_frame.sender(&_reg_map);
while (!fill_from_frame()) { while (!fill_from_frame()) {
_prev_frame = _frame;
_frame = _frame.sender(&_reg_map); _frame = _frame.sender(&_reg_map);
} }
} }
@ -534,6 +536,37 @@ void vframeStreamCommon::skip_reflection_related_frames() {
} }
} }
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 #ifndef PRODUCT
void vframe::print() { void vframe::print() {

View file

@ -278,12 +278,16 @@ class MonitorInfo : public ResourceObj {
class vframeStreamCommon : StackObj { class vframeStreamCommon : StackObj {
protected: protected:
// common // common
frame _prev_frame;
frame _frame; frame _frame;
JavaThread* _thread; JavaThread* _thread;
RegisterMap _reg_map; RegisterMap _reg_map;
enum { interpreted_mode, compiled_mode, at_end_mode } _mode; enum { interpreted_mode, compiled_mode, at_end_mode } _mode;
// For compiled_mode
int _decode_offset;
int _sender_decode_offset; int _sender_decode_offset;
int _vframe_id;
// Cached information // Cached information
Method* _method; Method* _method;
@ -320,6 +324,8 @@ class vframeStreamCommon : StackObj {
return (CompiledMethod*) cb(); return (CompiledMethod*) cb();
} }
javaVFrame* asJavaVFrame();
// Frame type // Frame type
inline bool is_interpreted_frame() const; inline bool is_interpreted_frame() const;
inline bool is_entry_frame() const; inline bool is_entry_frame() const;

View file

@ -44,6 +44,7 @@ inline void vframeStreamCommon::next() {
// handle general case // handle general case
do { do {
_prev_frame = _frame;
_frame = _frame.sender(&_reg_map); _frame = _frame.sender(&_reg_map);
} while (!fill_from_frame()); } while (!fill_from_frame());
} }
@ -59,6 +60,7 @@ inline vframeStream::vframeStream(JavaThread* thread, bool stop_at_java_call_stu
_frame = _thread->last_frame(); _frame = _thread->last_frame();
while (!fill_from_frame()) { while (!fill_from_frame()) {
_prev_frame = _frame;
_frame = _frame.sender(&_reg_map); _frame = _frame.sender(&_reg_map);
} }
} }
@ -68,12 +70,14 @@ inline bool vframeStreamCommon::fill_in_compiled_inlined_sender() {
return false; return false;
} }
fill_from_compiled_frame(_sender_decode_offset); fill_from_compiled_frame(_sender_decode_offset);
++_vframe_id;
return true; return true;
} }
inline void vframeStreamCommon::fill_from_compiled_frame(int decode_offset) { inline void vframeStreamCommon::fill_from_compiled_frame(int decode_offset) {
_mode = compiled_mode; _mode = compiled_mode;
_decode_offset = decode_offset;
// Range check to detect ridiculous offsets. // Range check to detect ridiculous offsets.
if (decode_offset == DebugInformationRecorder::serialized_null || if (decode_offset == DebugInformationRecorder::serialized_null ||
@ -118,6 +122,8 @@ inline void vframeStreamCommon::fill_from_compiled_frame(int decode_offset) {
inline void vframeStreamCommon::fill_from_compiled_native_frame() { inline void vframeStreamCommon::fill_from_compiled_native_frame() {
_mode = compiled_mode; _mode = compiled_mode;
_sender_decode_offset = DebugInformationRecorder::serialized_null; _sender_decode_offset = DebugInformationRecorder::serialized_null;
_decode_offset = DebugInformationRecorder::serialized_null;
_vframe_id = 0;
_method = nm()->method(); _method = nm()->method();
_bci = 0; _bci = 0;
} }
@ -187,6 +193,7 @@ inline bool vframeStreamCommon::fill_from_frame() {
decode_offset = pc_desc->scope_decode_offset(); decode_offset = pc_desc->scope_decode_offset();
} }
fill_from_compiled_frame(decode_offset); fill_from_compiled_frame(decode_offset);
_vframe_id = 0;
} }
return true; return true;
} }

View file

@ -252,6 +252,14 @@ compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, Java
guarantee(_scope != NULL, "scope must be present"); 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 { bool compiledVFrame::is_top() const {
// FIX IT: Remove this when new native stubs are in place // FIX IT: Remove this when new native stubs are in place

View file

@ -72,6 +72,9 @@ class compiledVFrame: public javaVFrame {
// Returns the scopeDesc // Returns the scopeDesc
ScopeDesc* scope() const { return _scope; } 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) // Returns SynchronizationEntryBCI or bci() (used for synchronization)
int raw_bci() const; int raw_bci() const;