--- 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) {
--- 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;
--- 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() {
--- 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;
--- 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;
}
--- 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
--- 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;