mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 06:14:49 +02:00
8255208: CodeStrings passed to Disassembler::decode are ignored
Reviewed-by: kvn, iklam
This commit is contained in:
parent
8e5dff08fa
commit
c1524c59ad
11 changed files with 118 additions and 204 deletions
|
@ -140,7 +140,7 @@ CodeBuffer::~CodeBuffer() {
|
|||
|
||||
// Claim is that stack allocation ensures resources are cleaned up.
|
||||
// This is resource clean up, let's hope that all were properly copied out.
|
||||
free_strings();
|
||||
NOT_PRODUCT(free_strings();)
|
||||
|
||||
#ifdef ASSERT
|
||||
// Save allocation type to execute assert in ~ResourceObj()
|
||||
|
@ -267,13 +267,14 @@ bool CodeBuffer::is_backward_branch(Label& L) {
|
|||
return L.is_bound() && insts_end() <= locator_address(L.loc());
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
address CodeBuffer::decode_begin() {
|
||||
address begin = _insts.start();
|
||||
if (_decode_begin != NULL && _decode_begin > begin)
|
||||
begin = _decode_begin;
|
||||
return begin;
|
||||
}
|
||||
|
||||
#endif // !PRODUCT
|
||||
|
||||
GrowableArray<int>* CodeBuffer::create_patch_overflow() {
|
||||
if (_overflow_arena == NULL) {
|
||||
|
@ -752,7 +753,7 @@ void CodeBuffer::copy_code_to(CodeBlob* dest_blob) {
|
|||
relocate_code_to(&dest);
|
||||
|
||||
// transfer strings and comments from buffer to blob
|
||||
dest_blob->set_strings(_code_strings);
|
||||
NOT_PRODUCT(dest_blob->set_strings(_code_strings);)
|
||||
|
||||
// Done moving code bytes; were they the right size?
|
||||
assert((int)align_up(dest.total_content_size(), oopSize) == dest_blob->content_size(), "sanity");
|
||||
|
@ -957,12 +958,11 @@ void CodeBuffer::expand(CodeSection* which_cs, csize_t amount) {
|
|||
debug_only(Copy::fill_to_bytes(bxp->_total_start, bxp->_total_size,
|
||||
badCodeHeapFreeVal));
|
||||
|
||||
_decode_begin = NULL; // sanity
|
||||
|
||||
// Make certain that the new sections are all snugly inside the new blob.
|
||||
verify_section_allocation();
|
||||
|
||||
#ifndef PRODUCT
|
||||
_decode_begin = NULL; // sanity
|
||||
if (PrintNMethods && (WizardMode || Verbose)) {
|
||||
tty->print("expanded CodeBuffer:");
|
||||
this->print();
|
||||
|
@ -1032,10 +1032,6 @@ void CodeBuffer::log_section_sizes(const char* name) {
|
|||
|
||||
#ifndef PRODUCT
|
||||
|
||||
void CodeSection::decode() {
|
||||
Disassembler::decode(start(), end());
|
||||
}
|
||||
|
||||
void CodeBuffer::block_comment(intptr_t offset, const char * comment) {
|
||||
if (_collect_comments) {
|
||||
_code_strings.add_comment(offset, comment);
|
||||
|
@ -1054,8 +1050,12 @@ class CodeString: public CHeapObj<mtCode> {
|
|||
CodeString* _prev;
|
||||
intptr_t _offset;
|
||||
|
||||
static long allocated_code_strings;
|
||||
|
||||
~CodeString() {
|
||||
assert(_next == NULL && _prev == NULL, "wrong interface for freeing list");
|
||||
allocated_code_strings--;
|
||||
log_trace(codestrings)("Freeing CodeString [%s] (%p)", _string, (void*)_string);
|
||||
os::free((void*)_string);
|
||||
}
|
||||
|
||||
|
@ -1064,7 +1064,9 @@ class CodeString: public CHeapObj<mtCode> {
|
|||
public:
|
||||
CodeString(const char * string, intptr_t offset = -1)
|
||||
: _next(NULL), _prev(NULL), _offset(offset) {
|
||||
allocated_code_strings++;
|
||||
_string = os::strdup(string, mtCode);
|
||||
log_trace(codestrings)("Created CodeString [%s] (%p)", _string, (void*)_string);
|
||||
}
|
||||
|
||||
const char * string() const { return _string; }
|
||||
|
@ -1094,6 +1096,10 @@ class CodeString: public CHeapObj<mtCode> {
|
|||
}
|
||||
};
|
||||
|
||||
// For tracing statistics. Will use raw increment/decrement, so it might not be
|
||||
// exact
|
||||
long CodeString::allocated_code_strings = 0;
|
||||
|
||||
CodeString* CodeStrings::find(intptr_t offset) const {
|
||||
CodeString* a = _strings->first_comment();
|
||||
while (a != NULL && a->offset() != offset) {
|
||||
|
@ -1116,7 +1122,7 @@ void CodeStrings::add_comment(intptr_t offset, const char * comment) {
|
|||
CodeString* c = new CodeString(comment, offset);
|
||||
CodeString* inspos = (_strings == NULL) ? NULL : find_last(offset);
|
||||
|
||||
if (inspos) {
|
||||
if (inspos != NULL) {
|
||||
// insert after already existing comments with same offset
|
||||
c->set_next(inspos->next());
|
||||
inspos->set_next(c);
|
||||
|
@ -1130,21 +1136,10 @@ void CodeStrings::add_comment(intptr_t offset, const char * comment) {
|
|||
}
|
||||
}
|
||||
|
||||
void CodeStrings::assign(CodeStrings& other) {
|
||||
other.check_valid();
|
||||
assert(is_null(), "Cannot assign onto non-empty CodeStrings");
|
||||
_strings = other._strings;
|
||||
_strings_last = other._strings_last;
|
||||
#ifdef ASSERT
|
||||
_defunct = false;
|
||||
#endif
|
||||
other.set_null_and_invalidate();
|
||||
}
|
||||
|
||||
// Deep copy of CodeStrings for consistent memory management.
|
||||
// Only used for actual disassembly so this is cheaper than reference counting
|
||||
// for the "normal" fastdebug case.
|
||||
void CodeStrings::copy(CodeStrings& other) {
|
||||
log_debug(codestrings)("Copying %d Codestring(s)", other.count());
|
||||
|
||||
other.check_valid();
|
||||
check_valid();
|
||||
assert(is_null(), "Cannot copy onto non-empty CodeStrings");
|
||||
|
@ -1152,7 +1147,11 @@ void CodeStrings::copy(CodeStrings& other) {
|
|||
CodeString** ps = &_strings;
|
||||
CodeString* prev = NULL;
|
||||
while (n != NULL) {
|
||||
if (n->is_comment()) {
|
||||
*ps = new CodeString(n->string(), n->offset());
|
||||
} else {
|
||||
*ps = new CodeString(n->string());
|
||||
}
|
||||
(*ps)->_prev = prev;
|
||||
prev = *ps;
|
||||
ps = &((*ps)->_next);
|
||||
|
@ -1162,13 +1161,6 @@ void CodeStrings::copy(CodeStrings& other) {
|
|||
|
||||
const char* CodeStrings::_prefix = " ;; "; // default: can be changed via set_prefix
|
||||
|
||||
// Check if any block comments are pending for the given offset.
|
||||
bool CodeStrings::has_block_comment(intptr_t offset) const {
|
||||
if (_strings == NULL) return false;
|
||||
CodeString* c = find(offset);
|
||||
return c != NULL;
|
||||
}
|
||||
|
||||
void CodeStrings::print_block_comment(outputStream* stream, intptr_t offset) const {
|
||||
check_valid();
|
||||
if (_strings != NULL) {
|
||||
|
@ -1184,8 +1176,19 @@ void CodeStrings::print_block_comment(outputStream* stream, intptr_t offset) con
|
|||
}
|
||||
}
|
||||
|
||||
// Also sets isNull()
|
||||
int CodeStrings::count() const {
|
||||
int i = 0;
|
||||
CodeString* s = _strings;
|
||||
while (s != NULL) {
|
||||
i++;
|
||||
s = s->_next;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
// Also sets is_null()
|
||||
void CodeStrings::free() {
|
||||
log_debug(codestrings)("Freeing %d out of approx. %ld CodeString(s), ", count(), CodeString::allocated_code_strings);
|
||||
CodeString* n = _strings;
|
||||
while (n) {
|
||||
// unlink the node from the list saving a pointer to the next
|
||||
|
@ -1215,7 +1218,7 @@ const char* CodeStrings::add_string(const char * string) {
|
|||
|
||||
void CodeBuffer::decode() {
|
||||
ttyLocker ttyl;
|
||||
Disassembler::decode(decode_begin(), insts_end(), tty);
|
||||
Disassembler::decode(decode_begin(), insts_end(), tty NOT_PRODUCT(COMMA &strings()));
|
||||
_decode_begin = insts_end();
|
||||
}
|
||||
|
||||
|
@ -1246,10 +1249,4 @@ void CodeBuffer::print() {
|
|||
}
|
||||
}
|
||||
|
||||
// Directly disassemble code buffer.
|
||||
void CodeBuffer::decode(address start, address end) {
|
||||
ttyLocker ttyl;
|
||||
Disassembler::decode(this, start, end, tty);
|
||||
}
|
||||
|
||||
#endif // PRODUCT
|
||||
|
|
|
@ -284,20 +284,18 @@ private:
|
|||
bool _defunct; // Zero bit pattern is "valid", see memset call in decode_env::decode_env
|
||||
#endif
|
||||
static const char* _prefix; // defaults to " ;; "
|
||||
#endif
|
||||
|
||||
CodeString* find(intptr_t offset) const;
|
||||
CodeString* find_last(intptr_t offset) const;
|
||||
|
||||
void set_null_and_invalidate() {
|
||||
#ifndef PRODUCT
|
||||
_strings = NULL;
|
||||
_strings_last = NULL;
|
||||
#ifdef ASSERT
|
||||
_defunct = true;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
public:
|
||||
CodeStrings() {
|
||||
|
@ -310,6 +308,7 @@ public:
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
bool is_null() {
|
||||
#ifdef ASSERT
|
||||
return _strings == NULL;
|
||||
|
@ -318,30 +317,25 @@ public:
|
|||
#endif
|
||||
}
|
||||
|
||||
const char* add_string(const char * string) PRODUCT_RETURN_(return NULL;);
|
||||
const char* add_string(const char * string);
|
||||
|
||||
void add_comment(intptr_t offset, const char * comment) PRODUCT_RETURN;
|
||||
bool has_block_comment(intptr_t offset) const;
|
||||
void print_block_comment(outputStream* stream, intptr_t offset) const PRODUCT_RETURN;
|
||||
// MOVE strings from other to this; invalidate other.
|
||||
void assign(CodeStrings& other) PRODUCT_RETURN;
|
||||
void add_comment(intptr_t offset, const char * comment);
|
||||
void print_block_comment(outputStream* stream, intptr_t offset) const;
|
||||
int count() const;
|
||||
// COPY strings from other to this; leave other valid.
|
||||
void copy(CodeStrings& other) PRODUCT_RETURN;
|
||||
void copy(CodeStrings& other);
|
||||
// FREE strings; invalidate this.
|
||||
void free() PRODUCT_RETURN;
|
||||
void free();
|
||||
|
||||
// Guarantee that _strings are used at most once; assign and free invalidate a buffer.
|
||||
inline void check_valid() const {
|
||||
#ifdef ASSERT
|
||||
assert(!_defunct, "Use of invalid CodeStrings");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void set_prefix(const char *prefix) {
|
||||
#ifndef PRODUCT
|
||||
_prefix = prefix;
|
||||
#endif
|
||||
}
|
||||
#endif // !PRODUCT
|
||||
};
|
||||
|
||||
// A CodeBuffer describes a memory space into which assembly
|
||||
|
@ -410,8 +404,7 @@ class CodeBuffer: public StackObj {
|
|||
csize_t _total_size; // size in bytes of combined memory buffer
|
||||
|
||||
OopRecorder* _oop_recorder;
|
||||
CodeStrings _code_strings;
|
||||
bool _collect_comments; // Indicate if we need to collect block comments at all.
|
||||
|
||||
OopRecorder _default_oop_recorder; // override with initialize_oop_recorder
|
||||
Arena* _overflow_arena;
|
||||
|
||||
|
@ -421,8 +414,12 @@ class CodeBuffer: public StackObj {
|
|||
bool _immutable_PIC;
|
||||
#endif
|
||||
|
||||
#ifndef PRODUCT
|
||||
CodeStrings _code_strings;
|
||||
bool _collect_comments; // Indicate if we need to collect block comments at all.
|
||||
address _decode_begin; // start address for decode
|
||||
address decode_begin();
|
||||
#endif
|
||||
|
||||
void initialize_misc(const char * name) {
|
||||
// all pointers other than code_start/end and those inside the sections
|
||||
|
@ -431,14 +428,15 @@ class CodeBuffer: public StackObj {
|
|||
_before_expand = NULL;
|
||||
_blob = NULL;
|
||||
_oop_recorder = NULL;
|
||||
_decode_begin = NULL;
|
||||
_overflow_arena = NULL;
|
||||
_code_strings = CodeStrings();
|
||||
_last_insn = NULL;
|
||||
#if INCLUDE_AOT
|
||||
_immutable_PIC = false;
|
||||
#endif
|
||||
|
||||
#ifndef PRODUCT
|
||||
_decode_begin = NULL;
|
||||
_code_strings = CodeStrings();
|
||||
// Collect block comments, but restrict collection to cases where a disassembly is output.
|
||||
_collect_comments = ( PrintAssembly
|
||||
|| PrintStubCode
|
||||
|
@ -447,6 +445,7 @@ class CodeBuffer: public StackObj {
|
|||
|| PrintSignatureHandlers
|
||||
|| UnlockDiagnosticVMOptions
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
void initialize(address code_start, csize_t code_size) {
|
||||
|
@ -636,34 +635,26 @@ class CodeBuffer: public StackObj {
|
|||
void initialize_oop_recorder(OopRecorder* r);
|
||||
|
||||
OopRecorder* oop_recorder() const { return _oop_recorder; }
|
||||
CodeStrings& strings() { return _code_strings; }
|
||||
|
||||
address last_insn() const { return _last_insn; }
|
||||
void set_last_insn(address a) { _last_insn = a; }
|
||||
void clear_last_insn() { set_last_insn(NULL); }
|
||||
|
||||
#ifndef PRODUCT
|
||||
CodeStrings& strings() { return _code_strings; }
|
||||
|
||||
void free_strings() {
|
||||
if (!_code_strings.is_null()) {
|
||||
_code_strings.free(); // sets _strings Null as a side-effect.
|
||||
}
|
||||
}
|
||||
|
||||
// Directly disassemble code buffer.
|
||||
// Print the comment associated with offset on stream, if there is one.
|
||||
virtual void print_block_comment(outputStream* stream, address block_begin) {
|
||||
#ifndef PRODUCT
|
||||
intptr_t offset = (intptr_t)(block_begin - _total_start); // I assume total_start is not correct for all code sections.
|
||||
_code_strings.print_block_comment(stream, offset);
|
||||
#endif
|
||||
}
|
||||
bool has_block_comment(address block_begin) {
|
||||
#ifndef PRODUCT
|
||||
intptr_t offset = (intptr_t)(block_begin - _total_start); // I assume total_start is not correct for all code sections.
|
||||
return _code_strings.has_block_comment(offset);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Code generation
|
||||
void relocate(address at, RelocationHolder const& rspec, int format = 0) {
|
||||
|
|
|
@ -87,8 +87,8 @@ CodeBlob::CodeBlob(const char* name, CompilerType type, const CodeBlobLayout& la
|
|||
_relocation_end(layout.relocation_end()),
|
||||
_oop_maps(oop_maps),
|
||||
_caller_must_gc_arguments(caller_must_gc_arguments),
|
||||
_strings(CodeStrings()),
|
||||
_name(name)
|
||||
NOT_PRODUCT(COMMA _strings(CodeStrings()))
|
||||
{
|
||||
assert(is_aligned(layout.size(), oopSize), "unaligned size");
|
||||
assert(is_aligned(layout.header_size(), oopSize), "unaligned size");
|
||||
|
@ -115,8 +115,8 @@ CodeBlob::CodeBlob(const char* name, CompilerType type, const CodeBlobLayout& la
|
|||
_relocation_begin(layout.relocation_begin()),
|
||||
_relocation_end(layout.relocation_end()),
|
||||
_caller_must_gc_arguments(caller_must_gc_arguments),
|
||||
_strings(CodeStrings()),
|
||||
_name(name)
|
||||
NOT_PRODUCT(COMMA _strings(CodeStrings()))
|
||||
{
|
||||
assert(is_aligned(_size, oopSize), "unaligned size");
|
||||
assert(is_aligned(_header_size, oopSize), "unaligned size");
|
||||
|
@ -158,7 +158,7 @@ RuntimeBlob::RuntimeBlob(
|
|||
void CodeBlob::flush() {
|
||||
FREE_C_HEAP_ARRAY(unsigned char, _oop_maps);
|
||||
_oop_maps = NULL;
|
||||
_strings.free();
|
||||
NOT_PRODUCT(_strings.free();)
|
||||
}
|
||||
|
||||
void CodeBlob::set_oop_maps(OopMapSet* p) {
|
||||
|
|
|
@ -110,10 +110,12 @@ protected:
|
|||
|
||||
ImmutableOopMapSet* _oop_maps; // OopMap for this CodeBlob
|
||||
bool _caller_must_gc_arguments;
|
||||
CodeStrings _strings;
|
||||
|
||||
const char* _name;
|
||||
S390_ONLY(int _ctable_offset;)
|
||||
|
||||
NOT_PRODUCT(CodeStrings _strings;)
|
||||
|
||||
CodeBlob(const char* name, CompilerType type, const CodeBlobLayout& layout, int frame_complete_offset, int frame_size, ImmutableOopMapSet* oop_maps, bool caller_must_gc_arguments);
|
||||
CodeBlob(const char* name, CompilerType type, const CodeBlobLayout& layout, CodeBuffer* cb, int frame_complete_offset, int frame_size, OopMapSet* oop_maps, bool caller_must_gc_arguments);
|
||||
|
||||
|
@ -231,29 +233,20 @@ public:
|
|||
void dump_for_addr(address addr, outputStream* st, bool verbose) const;
|
||||
void print_code();
|
||||
|
||||
bool has_block_comment(address block_begin) const {
|
||||
intptr_t offset = (intptr_t)(block_begin - code_begin());
|
||||
return _strings.has_block_comment(offset);
|
||||
}
|
||||
// Print the comment associated with offset on stream, if there is one
|
||||
virtual void print_block_comment(outputStream* stream, address block_begin) const {
|
||||
#ifndef PRODUCT
|
||||
intptr_t offset = (intptr_t)(block_begin - code_begin());
|
||||
_strings.print_block_comment(stream, offset);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Transfer ownership of comments to this CodeBlob
|
||||
#ifndef PRODUCT
|
||||
void set_strings(CodeStrings& strings) {
|
||||
assert(!is_aot(), "invalid on aot");
|
||||
_strings.assign(strings);
|
||||
}
|
||||
|
||||
static ByteSize name_field_offset() {
|
||||
return byte_offset_of(CodeBlob, _name);
|
||||
}
|
||||
|
||||
static ByteSize oop_maps_field_offset() {
|
||||
return byte_offset_of(CodeBlob, _oop_maps);
|
||||
_strings.copy(strings);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class CodeBlobLayout : public StackObj {
|
||||
|
|
|
@ -695,9 +695,7 @@ public:
|
|||
CodeBlob::print_block_comment(stream, block_begin);
|
||||
#endif
|
||||
}
|
||||
bool has_block_comment(address block_begin) {
|
||||
return CodeBlob::has_block_comment(block_begin);
|
||||
}
|
||||
|
||||
void print_nmethod_labels(outputStream* stream, address block_begin, bool print_section_labels=true) const;
|
||||
const char* nmethod_section_label(address pos) const;
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ class decode_env {
|
|||
CodeBuffer* _codeBuffer; // != NULL only when decoding a CodeBuffer
|
||||
CodeBlob* _codeBlob; // != NULL only when decoding a CodeBlob
|
||||
nmethod* _nm; // != NULL only when decoding a nmethod
|
||||
CodeStrings _strings;
|
||||
|
||||
address _start; // != NULL when decoding a range of unknown type
|
||||
address _end; // != NULL when decoding a range of unknown type
|
||||
|
||||
|
@ -77,6 +77,7 @@ class decode_env {
|
|||
bool _print_help;
|
||||
bool _helpPrinted;
|
||||
static bool _optionsParsed;
|
||||
NOT_PRODUCT(const CodeStrings* _strings;)
|
||||
|
||||
enum {
|
||||
tabspacing = 8
|
||||
|
@ -214,12 +215,11 @@ class decode_env {
|
|||
}
|
||||
|
||||
public:
|
||||
decode_env(CodeBuffer* code, outputStream* output);
|
||||
decode_env(CodeBlob* code, outputStream* output, CodeStrings c = CodeStrings() /* , ptrdiff_t offset */);
|
||||
decode_env(nmethod* code, outputStream* output, CodeStrings c = CodeStrings());
|
||||
decode_env(CodeBlob* code, outputStream* output);
|
||||
decode_env(nmethod* code, outputStream* output);
|
||||
// Constructor for a 'decode_env' to decode an arbitrary
|
||||
// piece of memory, hopefully containing code.
|
||||
decode_env(address start, address end, outputStream* output);
|
||||
decode_env(address start, address end, outputStream* output, const CodeStrings* strings = NULL);
|
||||
|
||||
// Add 'original_start' argument which is the the original address
|
||||
// the instructions were located at (if this is not equal to 'start').
|
||||
|
@ -322,34 +322,10 @@ void decode_env::print_hook_comments(address pc, bool newline) {
|
|||
}
|
||||
}
|
||||
|
||||
decode_env::decode_env(CodeBuffer* code, outputStream* output) :
|
||||
decode_env::decode_env(CodeBlob* code, outputStream* output) :
|
||||
_output(output ? output : tty),
|
||||
_codeBuffer(code),
|
||||
_codeBlob(NULL),
|
||||
_nm(NULL),
|
||||
_strings(),
|
||||
_start(NULL),
|
||||
_end(NULL),
|
||||
_option_buf(),
|
||||
_print_raw(0),
|
||||
_cur_insn(NULL),
|
||||
_bytes_per_line(0),
|
||||
_pre_decode_alignment(0),
|
||||
_post_decode_alignment(0),
|
||||
_print_file_name(false),
|
||||
_print_help(false),
|
||||
_helpPrinted(false) {
|
||||
|
||||
memset(_option_buf, 0, sizeof(_option_buf));
|
||||
process_options(_output);
|
||||
}
|
||||
|
||||
decode_env::decode_env(CodeBlob* code, outputStream* output, CodeStrings c) :
|
||||
_output(output ? output : tty),
|
||||
_codeBuffer(NULL),
|
||||
_codeBlob(code),
|
||||
_nm(_codeBlob != NULL && _codeBlob->is_nmethod() ? (nmethod*) code : NULL),
|
||||
_strings(),
|
||||
_start(NULL),
|
||||
_end(NULL),
|
||||
_option_buf(),
|
||||
|
@ -360,19 +336,18 @@ decode_env::decode_env(CodeBlob* code, outputStream* output, CodeStrings c) :
|
|||
_post_decode_alignment(0),
|
||||
_print_file_name(false),
|
||||
_print_help(false),
|
||||
_helpPrinted(false) {
|
||||
_helpPrinted(false)
|
||||
NOT_PRODUCT(COMMA _strings(NULL)) {
|
||||
|
||||
memset(_option_buf, 0, sizeof(_option_buf));
|
||||
_strings.copy(c);
|
||||
process_options(_output);
|
||||
|
||||
}
|
||||
|
||||
decode_env::decode_env(nmethod* code, outputStream* output, CodeStrings c) :
|
||||
decode_env::decode_env(nmethod* code, outputStream* output) :
|
||||
_output(output ? output : tty),
|
||||
_codeBuffer(NULL),
|
||||
_codeBlob(NULL),
|
||||
_nm(code),
|
||||
_strings(),
|
||||
_start(_nm->code_begin()),
|
||||
_end(_nm->code_end()),
|
||||
_option_buf(),
|
||||
|
@ -383,21 +358,19 @@ decode_env::decode_env(nmethod* code, outputStream* output, CodeStrings c) :
|
|||
_post_decode_alignment(0),
|
||||
_print_file_name(false),
|
||||
_print_help(false),
|
||||
_helpPrinted(false) {
|
||||
_helpPrinted(false)
|
||||
NOT_PRODUCT(COMMA _strings(NULL)) {
|
||||
|
||||
memset(_option_buf, 0, sizeof(_option_buf));
|
||||
_strings.copy(c);
|
||||
process_options(_output);
|
||||
}
|
||||
|
||||
// Constructor for a 'decode_env' to decode a memory range [start, end)
|
||||
// of unknown origin, assuming it contains code.
|
||||
decode_env::decode_env(address start, address end, outputStream* output) :
|
||||
decode_env::decode_env(address start, address end, outputStream* output, const CodeStrings* c) :
|
||||
_output(output ? output : tty),
|
||||
_codeBuffer(NULL),
|
||||
_codeBlob(NULL),
|
||||
_nm(NULL),
|
||||
_strings(),
|
||||
_start(start),
|
||||
_end(end),
|
||||
_option_buf(),
|
||||
|
@ -408,7 +381,8 @@ decode_env::decode_env(address start, address end, outputStream* output) :
|
|||
_post_decode_alignment(0),
|
||||
_print_file_name(false),
|
||||
_print_help(false),
|
||||
_helpPrinted(false) {
|
||||
_helpPrinted(false)
|
||||
NOT_PRODUCT(COMMA _strings(c)) {
|
||||
|
||||
assert(start < end, "Range must have a positive size, [" PTR_FORMAT ".." PTR_FORMAT ").", p2i(start), p2i(end));
|
||||
memset(_option_buf, 0, sizeof(_option_buf));
|
||||
|
@ -682,10 +656,11 @@ void decode_env::print_insn_labels() {
|
|||
if (_codeBlob != NULL) {
|
||||
_codeBlob->print_block_comment(st, p);
|
||||
}
|
||||
if (_codeBuffer != NULL) {
|
||||
_codeBuffer->print_block_comment(st, p);
|
||||
#ifndef PRODUCT
|
||||
if (_strings != NULL) {
|
||||
_strings->print_block_comment(st, (intptr_t)(p - _start));
|
||||
}
|
||||
_strings.print_block_comment(st, (intptr_t)(p - _start));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -919,49 +894,13 @@ bool Disassembler::load_library(outputStream* st) {
|
|||
}
|
||||
|
||||
|
||||
// Directly disassemble code buffer.
|
||||
void Disassembler::decode(CodeBuffer* cb, address start, address end, outputStream* st) {
|
||||
#if defined(SUPPORT_ASSEMBLY) || defined(SUPPORT_ABSTRACT_ASSEMBLY)
|
||||
//---< Test memory before decoding >---
|
||||
if (!(cb->contains(start) && cb->contains(end))) {
|
||||
//---< Allow output suppression, but prevent writing to a NULL stream. Could happen with +PrintStubCode. >---
|
||||
if (st != NULL) {
|
||||
st->print("Memory range [" PTR_FORMAT ".." PTR_FORMAT "] not contained in CodeBuffer", p2i(start), p2i(end));
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!os::is_readable_range(start, end)) {
|
||||
//---< Allow output suppression, but prevent writing to a NULL stream. Could happen with +PrintStubCode. >---
|
||||
if (st != NULL) {
|
||||
st->print("Memory range [" PTR_FORMAT ".." PTR_FORMAT "] not readable", p2i(start), p2i(end));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
decode_env env(cb, st);
|
||||
env.output()->print_cr("--------------------------------------------------------------------------------");
|
||||
env.output()->print("Decoding CodeBuffer (" PTR_FORMAT ")", p2i(cb));
|
||||
if (cb->name() != NULL) {
|
||||
env.output()->print(", name: %s,", cb->name());
|
||||
}
|
||||
env.output()->print_cr(" at [" PTR_FORMAT ", " PTR_FORMAT "] " JLONG_FORMAT " bytes", p2i(start), p2i(end), ((jlong)(end - start)));
|
||||
|
||||
if (is_abstract()) {
|
||||
AbstractDisassembler::decode_abstract(start, end, env.output(), Assembler::instr_maxlen());
|
||||
} else {
|
||||
env.decode_instructions(start, end);
|
||||
}
|
||||
env.output()->print_cr("--------------------------------------------------------------------------------");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Directly disassemble code blob.
|
||||
void Disassembler::decode(CodeBlob* cb, outputStream* st, CodeStrings c) {
|
||||
void Disassembler::decode(CodeBlob* cb, outputStream* st) {
|
||||
#if defined(SUPPORT_ASSEMBLY) || defined(SUPPORT_ABSTRACT_ASSEMBLY)
|
||||
if (cb->is_nmethod()) {
|
||||
// If we have an nmethod at hand,
|
||||
// call the specialized decoder directly.
|
||||
decode((nmethod*)cb, st, c);
|
||||
decode((nmethod*)cb, st);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -999,7 +938,7 @@ void Disassembler::decode(CodeBlob* cb, outputStream* st, CodeStrings c) {
|
|||
// Decode a nmethod.
|
||||
// This includes printing the constant pool and all code segments.
|
||||
// The nmethod data structures (oop maps, relocations and the like) are not printed.
|
||||
void Disassembler::decode(nmethod* nm, outputStream* st, CodeStrings c) {
|
||||
void Disassembler::decode(nmethod* nm, outputStream* st) {
|
||||
#if defined(SUPPORT_ASSEMBLY) || defined(SUPPORT_ABSTRACT_ASSEMBLY)
|
||||
ttyLocker ttyl;
|
||||
|
||||
|
@ -1018,7 +957,7 @@ void Disassembler::decode(nmethod* nm, outputStream* st, CodeStrings c) {
|
|||
}
|
||||
|
||||
// Decode a range, given as [start address, end address)
|
||||
void Disassembler::decode(address start, address end, outputStream* st, CodeStrings c /*, ptrdiff_t offset */) {
|
||||
void Disassembler::decode(address start, address end, outputStream* st, const CodeStrings* c) {
|
||||
#if defined(SUPPORT_ASSEMBLY) || defined(SUPPORT_ABSTRACT_ASSEMBLY)
|
||||
//---< Test memory before decoding >---
|
||||
if (!os::is_readable_range(start, end)) {
|
||||
|
@ -1046,7 +985,7 @@ void Disassembler::decode(address start, address end, outputStream* st, CodeStri
|
|||
#endif
|
||||
{
|
||||
// This seems to be just a chunk of memory.
|
||||
decode_env env(start, end, st);
|
||||
decode_env env(start, end, st, c);
|
||||
env.output()->print_cr("--------------------------------------------------------------------------------");
|
||||
env.decode_instructions(start, end);
|
||||
env.output()->print_cr("--------------------------------------------------------------------------------");
|
||||
|
|
|
@ -28,7 +28,8 @@
|
|||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
#include "asm/assembler.hpp"
|
||||
#include "asm/codeBuffer.hpp"
|
||||
#include "code/codeBlob.hpp"
|
||||
#include "code/nmethod.hpp"
|
||||
#include "compiler/abstractDisassembler.hpp"
|
||||
#include "runtime/globals.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
@ -88,10 +89,10 @@ class Disassembler : public AbstractDisassembler {
|
|||
// about which decoding format is used.
|
||||
// We can also enforce using the abstract disassembler.
|
||||
static bool is_abstract() {
|
||||
if (!_tried_to_load_library /* && !UseAbstractDisassembler */) {
|
||||
if (!_tried_to_load_library) {
|
||||
load_library();
|
||||
}
|
||||
return ! _library_usable /* || UseAbstractDisassembler */; // Not available until DecodeErrorFile is supported.
|
||||
return ! _library_usable;
|
||||
}
|
||||
|
||||
// Check out if we are doing a live disassembly or a post-mortem
|
||||
|
@ -105,14 +106,12 @@ class Disassembler : public AbstractDisassembler {
|
|||
#endif
|
||||
}
|
||||
|
||||
// Directly disassemble code buffer.
|
||||
static void decode(CodeBuffer* cb, address start, address end, outputStream* st = NULL);
|
||||
// Directly disassemble code blob.
|
||||
static void decode(CodeBlob *cb, outputStream* st = NULL, CodeStrings c = CodeStrings());
|
||||
static void decode(CodeBlob *cb, outputStream* st = NULL);
|
||||
// Directly disassemble nmethod.
|
||||
static void decode(nmethod* nm, outputStream* st = NULL, CodeStrings c = CodeStrings());
|
||||
static void decode(nmethod* nm, outputStream* st = NULL);
|
||||
// Disassemble an arbitrary memory range.
|
||||
static void decode(address start, address end, outputStream* st = NULL, CodeStrings c = CodeStrings() /* , ptrdiff_t offset */);
|
||||
static void decode(address start, address end, outputStream* st = NULL, const CodeStrings* = NULL);
|
||||
|
||||
static void _hook(const char* file, int line, class MacroAssembler* masm);
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ void InterpreterCodelet::print_on(outputStream* st) const {
|
|||
|
||||
if (PrintInterpreter) {
|
||||
st->cr();
|
||||
Disassembler::decode(code_begin(), code_end(), st, DEBUG_ONLY(_strings) NOT_DEBUG(CodeStrings()));
|
||||
Disassembler::decode(code_begin(), code_end(), st DEBUG_ONLY(COMMA &_strings));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,8 @@ CodeletMark::~CodeletMark() {
|
|||
// Commit Codelet.
|
||||
int committed_code_size = (*_masm)->code()->pure_insts_size();
|
||||
if (committed_code_size) {
|
||||
AbstractInterpreter::code()->commit(committed_code_size, (*_masm)->code()->strings());
|
||||
CodeStrings cs NOT_PRODUCT(= (*_masm)->code()->strings());
|
||||
AbstractInterpreter::code()->commit(committed_code_size, cs);
|
||||
}
|
||||
// Make sure nobody can use _masm outside a CodeletMark lifespan.
|
||||
*_masm = NULL;
|
||||
|
|
|
@ -49,14 +49,14 @@ class InterpreterCodelet: public Stub {
|
|||
int _size; // the size in bytes
|
||||
const char* _description; // a description of the codelet, for debugging & printing
|
||||
Bytecodes::Code _bytecode; // associated bytecode if any
|
||||
DEBUG_ONLY(CodeStrings _strings;) // Comments for annotating assembler output.
|
||||
NOT_PRODUCT(CodeStrings _strings;) // Comments for annotating assembler output.
|
||||
|
||||
public:
|
||||
// Initialization/finalization
|
||||
void initialize(int size,
|
||||
CodeStrings& strings) { _size = size;
|
||||
DEBUG_ONLY(::new(&_strings) CodeStrings();)
|
||||
DEBUG_ONLY(_strings.assign(strings);) }
|
||||
NOT_PRODUCT(_strings = CodeStrings();)
|
||||
NOT_PRODUCT(_strings.copy(strings);) }
|
||||
void finalize() { ShouldNotCallThis(); }
|
||||
|
||||
// General info/converters
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
LOG_TAG(classhisto) \
|
||||
LOG_TAG(cleanup) \
|
||||
LOG_TAG(codecache) \
|
||||
NOT_PRODUCT(LOG_TAG(codestrings)) \
|
||||
LOG_TAG(compaction) \
|
||||
LOG_TAG(compilation) \
|
||||
LOG_TAG(condy) \
|
||||
|
|
|
@ -73,13 +73,13 @@ StubCodeGenerator::StubCodeGenerator(CodeBuffer* code, bool print_code) {
|
|||
}
|
||||
|
||||
StubCodeGenerator::~StubCodeGenerator() {
|
||||
if (PRODUCT_ONLY(_print_code) NOT_PRODUCT(true)) {
|
||||
#ifndef PRODUCT
|
||||
CodeBuffer* cbuf = _masm->code();
|
||||
CodeBlob* blob = CodeCache::find_blob_unsafe(cbuf->insts()->start());
|
||||
if (blob != NULL) {
|
||||
blob->set_strings(cbuf->strings());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void StubCodeGenerator::stub_prolog(StubCodeDesc* cdesc) {
|
||||
|
@ -88,21 +88,16 @@ void StubCodeGenerator::stub_prolog(StubCodeDesc* cdesc) {
|
|||
|
||||
void StubCodeGenerator::stub_epilog(StubCodeDesc* cdesc) {
|
||||
if (_print_code) {
|
||||
CodeStrings cs;
|
||||
ptrdiff_t offset = 0;
|
||||
#ifndef PRODUCT
|
||||
// Find the code strings in the outer CodeBuffer.
|
||||
CodeBuffer *outer_cbuf = _masm->code_section()->outer();
|
||||
cs = outer_cbuf->strings();
|
||||
// The offset from the start of the outer CodeBuffer to the start
|
||||
// of this stub.
|
||||
offset = cdesc->begin() - outer_cbuf->insts()->start();
|
||||
CodeStrings* cs = &outer_cbuf->strings();
|
||||
#endif
|
||||
ttyLocker ttyl;
|
||||
tty->print_cr("- - - [BEGIN] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
|
||||
cdesc->print_on(tty);
|
||||
tty->cr();
|
||||
Disassembler::decode(cdesc->begin(), cdesc->end(), tty, cs /*, offset */);
|
||||
Disassembler::decode(cdesc->begin(), cdesc->end(), tty NOT_PRODUCT(COMMA cs));
|
||||
tty->print_cr("- - - [END] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
|
||||
tty->cr();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue