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

@ -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;
_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 @@ ScopeDesc::ScopeDesc(const ScopeDesc* parent) {
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) {

@ -67,6 +67,9 @@ class ScopeDesc : public ResourceObj {
// 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 @@ class ScopeDesc : public ResourceObj {
// 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;

@ -452,8 +452,10 @@ vframeStream::vframeStream(JavaThread* thread, frame top_frame,
_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 @@ 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
void vframe::print() {

@ -278,12 +278,16 @@ class MonitorInfo : public ResourceObj {
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 @@ class vframeStreamCommon : StackObj {
return (CompiledMethod*) cb();
}
javaVFrame* asJavaVFrame();
// Frame type
inline bool is_interpreted_frame() const;
inline bool is_entry_frame() const;

@ -44,6 +44,7 @@ inline void vframeStreamCommon::next() {
// handle general case
do {
_prev_frame = _frame;
_frame = _frame.sender(&_reg_map);
} while (!fill_from_frame());
}
@ -59,6 +60,7 @@ inline vframeStream::vframeStream(JavaThread* thread, bool stop_at_java_call_stu
_frame = _thread->last_frame();
while (!fill_from_frame()) {
_prev_frame = _frame;
_frame = _frame.sender(&_reg_map);
}
}
@ -68,12 +70,14 @@ inline bool vframeStreamCommon::fill_in_compiled_inlined_sender() {
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_frame(int decode_offset) {
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 @@ inline bool vframeStreamCommon::fill_from_frame() {
decode_offset = pc_desc->scope_decode_offset();
}
fill_from_compiled_frame(decode_offset);
_vframe_id = 0;
}
return true;
}

@ -252,6 +252,14 @@ compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, Java
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

@ -72,6 +72,9 @@ class compiledVFrame: public javaVFrame {
// 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;