mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-18 10:04:42 +02:00
8215205: javaVFrame much slower than vframeStream
Reviewed-by: mchung, thartmann
This commit is contained in:
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;
|
_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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue