8255208: CodeStrings passed to Disassembler::decode are ignored

Reviewed-by: kvn, iklam
This commit is contained in:
Claes Redestad 2020-10-23 07:30:28 +00:00
parent 8e5dff08fa
commit c1524c59ad
11 changed files with 118 additions and 204 deletions

View file

@ -140,7 +140,7 @@ CodeBuffer::~CodeBuffer() {
// Claim is that stack allocation ensures resources are cleaned up. // Claim is that stack allocation ensures resources are cleaned up.
// This is resource clean up, let's hope that all were properly copied out. // This is resource clean up, let's hope that all were properly copied out.
free_strings(); NOT_PRODUCT(free_strings();)
#ifdef ASSERT #ifdef ASSERT
// Save allocation type to execute assert in ~ResourceObj() // 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()); return L.is_bound() && insts_end() <= locator_address(L.loc());
} }
#ifndef PRODUCT
address CodeBuffer::decode_begin() { address CodeBuffer::decode_begin() {
address begin = _insts.start(); address begin = _insts.start();
if (_decode_begin != NULL && _decode_begin > begin) if (_decode_begin != NULL && _decode_begin > begin)
begin = _decode_begin; begin = _decode_begin;
return begin; return begin;
} }
#endif // !PRODUCT
GrowableArray<int>* CodeBuffer::create_patch_overflow() { GrowableArray<int>* CodeBuffer::create_patch_overflow() {
if (_overflow_arena == NULL) { if (_overflow_arena == NULL) {
@ -752,7 +753,7 @@ void CodeBuffer::copy_code_to(CodeBlob* dest_blob) {
relocate_code_to(&dest); relocate_code_to(&dest);
// transfer strings and comments from buffer to blob // 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? // Done moving code bytes; were they the right size?
assert((int)align_up(dest.total_content_size(), oopSize) == dest_blob->content_size(), "sanity"); 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, debug_only(Copy::fill_to_bytes(bxp->_total_start, bxp->_total_size,
badCodeHeapFreeVal)); badCodeHeapFreeVal));
_decode_begin = NULL; // sanity
// Make certain that the new sections are all snugly inside the new blob. // Make certain that the new sections are all snugly inside the new blob.
verify_section_allocation(); verify_section_allocation();
#ifndef PRODUCT #ifndef PRODUCT
_decode_begin = NULL; // sanity
if (PrintNMethods && (WizardMode || Verbose)) { if (PrintNMethods && (WizardMode || Verbose)) {
tty->print("expanded CodeBuffer:"); tty->print("expanded CodeBuffer:");
this->print(); this->print();
@ -1032,10 +1032,6 @@ void CodeBuffer::log_section_sizes(const char* name) {
#ifndef PRODUCT #ifndef PRODUCT
void CodeSection::decode() {
Disassembler::decode(start(), end());
}
void CodeBuffer::block_comment(intptr_t offset, const char * comment) { void CodeBuffer::block_comment(intptr_t offset, const char * comment) {
if (_collect_comments) { if (_collect_comments) {
_code_strings.add_comment(offset, comment); _code_strings.add_comment(offset, comment);
@ -1054,8 +1050,12 @@ class CodeString: public CHeapObj<mtCode> {
CodeString* _prev; CodeString* _prev;
intptr_t _offset; intptr_t _offset;
static long allocated_code_strings;
~CodeString() { ~CodeString() {
assert(_next == NULL && _prev == NULL, "wrong interface for freeing list"); 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); os::free((void*)_string);
} }
@ -1064,12 +1064,14 @@ class CodeString: public CHeapObj<mtCode> {
public: public:
CodeString(const char * string, intptr_t offset = -1) CodeString(const char * string, intptr_t offset = -1)
: _next(NULL), _prev(NULL), _offset(offset) { : _next(NULL), _prev(NULL), _offset(offset) {
allocated_code_strings++;
_string = os::strdup(string, mtCode); _string = os::strdup(string, mtCode);
log_trace(codestrings)("Created CodeString [%s] (%p)", _string, (void*)_string);
} }
const char * string() const { return _string; } const char * string() const { return _string; }
intptr_t offset() const { assert(_offset >= 0, "offset for non comment?"); return _offset; } intptr_t offset() const { assert(_offset >= 0, "offset for non comment?"); return _offset; }
CodeString* next() const { return _next; } CodeString* next() const { return _next; }
void set_next(CodeString* next) { void set_next(CodeString* next) {
_next = next; _next = next;
@ -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* CodeStrings::find(intptr_t offset) const {
CodeString* a = _strings->first_comment(); CodeString* a = _strings->first_comment();
while (a != NULL && a->offset() != offset) { 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* c = new CodeString(comment, offset);
CodeString* inspos = (_strings == NULL) ? NULL : find_last(offset); CodeString* inspos = (_strings == NULL) ? NULL : find_last(offset);
if (inspos) { if (inspos != NULL) {
// insert after already existing comments with same offset // insert after already existing comments with same offset
c->set_next(inspos->next()); c->set_next(inspos->next());
inspos->set_next(c); 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. // 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) { void CodeStrings::copy(CodeStrings& other) {
log_debug(codestrings)("Copying %d Codestring(s)", other.count());
other.check_valid(); other.check_valid();
check_valid(); check_valid();
assert(is_null(), "Cannot copy onto non-empty CodeStrings"); assert(is_null(), "Cannot copy onto non-empty CodeStrings");
@ -1152,7 +1147,11 @@ void CodeStrings::copy(CodeStrings& other) {
CodeString** ps = &_strings; CodeString** ps = &_strings;
CodeString* prev = NULL; CodeString* prev = NULL;
while (n != NULL) { while (n != NULL) {
*ps = new CodeString(n->string(),n->offset()); if (n->is_comment()) {
*ps = new CodeString(n->string(), n->offset());
} else {
*ps = new CodeString(n->string());
}
(*ps)->_prev = prev; (*ps)->_prev = prev;
prev = *ps; prev = *ps;
ps = &((*ps)->_next); ps = &((*ps)->_next);
@ -1162,13 +1161,6 @@ void CodeStrings::copy(CodeStrings& other) {
const char* CodeStrings::_prefix = " ;; "; // default: can be changed via set_prefix 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 { void CodeStrings::print_block_comment(outputStream* stream, intptr_t offset) const {
check_valid(); check_valid();
if (_strings != NULL) { 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() { void CodeStrings::free() {
log_debug(codestrings)("Freeing %d out of approx. %ld CodeString(s), ", count(), CodeString::allocated_code_strings);
CodeString* n = _strings; CodeString* n = _strings;
while (n) { while (n) {
// unlink the node from the list saving a pointer to the next // 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() { void CodeBuffer::decode() {
ttyLocker ttyl; ttyLocker ttyl;
Disassembler::decode(decode_begin(), insts_end(), tty); Disassembler::decode(decode_begin(), insts_end(), tty NOT_PRODUCT(COMMA &strings()));
_decode_begin = insts_end(); _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 #endif // PRODUCT

View file

@ -284,20 +284,18 @@ private:
bool _defunct; // Zero bit pattern is "valid", see memset call in decode_env::decode_env bool _defunct; // Zero bit pattern is "valid", see memset call in decode_env::decode_env
#endif #endif
static const char* _prefix; // defaults to " ;; " static const char* _prefix; // defaults to " ;; "
#endif
CodeString* find(intptr_t offset) const; CodeString* find(intptr_t offset) const;
CodeString* find_last(intptr_t offset) const; CodeString* find_last(intptr_t offset) const;
void set_null_and_invalidate() { void set_null_and_invalidate() {
#ifndef PRODUCT
_strings = NULL; _strings = NULL;
_strings_last = NULL; _strings_last = NULL;
#ifdef ASSERT #ifdef ASSERT
_defunct = true; _defunct = true;
#endif
#endif #endif
} }
#endif
public: public:
CodeStrings() { CodeStrings() {
@ -310,6 +308,7 @@ public:
#endif #endif
} }
#ifndef PRODUCT
bool is_null() { bool is_null() {
#ifdef ASSERT #ifdef ASSERT
return _strings == NULL; return _strings == NULL;
@ -318,30 +317,25 @@ public:
#endif #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; void add_comment(intptr_t offset, const char * comment);
bool has_block_comment(intptr_t offset) const; void print_block_comment(outputStream* stream, intptr_t offset) const;
void print_block_comment(outputStream* stream, intptr_t offset) const PRODUCT_RETURN; int count() const;
// MOVE strings from other to this; invalidate other.
void assign(CodeStrings& other) PRODUCT_RETURN;
// COPY strings from other to this; leave other valid. // COPY strings from other to this; leave other valid.
void copy(CodeStrings& other) PRODUCT_RETURN; void copy(CodeStrings& other);
// FREE strings; invalidate this. // FREE strings; invalidate this.
void free() PRODUCT_RETURN; void free();
// Guarantee that _strings are used at most once; assign and free invalidate a buffer. // Guarantee that _strings are used at most once; assign and free invalidate a buffer.
inline void check_valid() const { inline void check_valid() const {
#ifdef ASSERT
assert(!_defunct, "Use of invalid CodeStrings"); assert(!_defunct, "Use of invalid CodeStrings");
#endif
} }
static void set_prefix(const char *prefix) { static void set_prefix(const char *prefix) {
#ifndef PRODUCT
_prefix = prefix; _prefix = prefix;
#endif
} }
#endif // !PRODUCT
}; };
// A CodeBuffer describes a memory space into which assembly // 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 csize_t _total_size; // size in bytes of combined memory buffer
OopRecorder* _oop_recorder; 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 OopRecorder _default_oop_recorder; // override with initialize_oop_recorder
Arena* _overflow_arena; Arena* _overflow_arena;
@ -421,8 +414,12 @@ class CodeBuffer: public StackObj {
bool _immutable_PIC; bool _immutable_PIC;
#endif #endif
address _decode_begin; // start address for decode #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(); address decode_begin();
#endif
void initialize_misc(const char * name) { void initialize_misc(const char * name) {
// all pointers other than code_start/end and those inside the sections // all pointers other than code_start/end and those inside the sections
@ -431,14 +428,15 @@ class CodeBuffer: public StackObj {
_before_expand = NULL; _before_expand = NULL;
_blob = NULL; _blob = NULL;
_oop_recorder = NULL; _oop_recorder = NULL;
_decode_begin = NULL;
_overflow_arena = NULL; _overflow_arena = NULL;
_code_strings = CodeStrings();
_last_insn = NULL; _last_insn = NULL;
#if INCLUDE_AOT #if INCLUDE_AOT
_immutable_PIC = false; _immutable_PIC = false;
#endif #endif
#ifndef PRODUCT
_decode_begin = NULL;
_code_strings = CodeStrings();
// Collect block comments, but restrict collection to cases where a disassembly is output. // Collect block comments, but restrict collection to cases where a disassembly is output.
_collect_comments = ( PrintAssembly _collect_comments = ( PrintAssembly
|| PrintStubCode || PrintStubCode
@ -447,6 +445,7 @@ class CodeBuffer: public StackObj {
|| PrintSignatureHandlers || PrintSignatureHandlers
|| UnlockDiagnosticVMOptions || UnlockDiagnosticVMOptions
); );
#endif
} }
void initialize(address code_start, csize_t code_size) { void initialize(address code_start, csize_t code_size) {
@ -635,35 +634,27 @@ class CodeBuffer: public StackObj {
// Override default oop recorder. // Override default oop recorder.
void initialize_oop_recorder(OopRecorder* r); void initialize_oop_recorder(OopRecorder* r);
OopRecorder* oop_recorder() const { return _oop_recorder; } OopRecorder* oop_recorder() const { return _oop_recorder; }
CodeStrings& strings() { return _code_strings; }
address last_insn() const { return _last_insn; } address last_insn() const { return _last_insn; }
void set_last_insn(address a) { _last_insn = a; } void set_last_insn(address a) { _last_insn = a; }
void clear_last_insn() { set_last_insn(NULL); } void clear_last_insn() { set_last_insn(NULL); }
#ifndef PRODUCT
CodeStrings& strings() { return _code_strings; }
void free_strings() { void free_strings() {
if (!_code_strings.is_null()) { if (!_code_strings.is_null()) {
_code_strings.free(); // sets _strings Null as a side-effect. _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. // Print the comment associated with offset on stream, if there is one.
virtual void print_block_comment(outputStream* stream, address block_begin) { 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. 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); _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 #endif
}
// Code generation // Code generation
void relocate(address at, RelocationHolder const& rspec, int format = 0) { void relocate(address at, RelocationHolder const& rspec, int format = 0) {

View file

@ -87,8 +87,8 @@ CodeBlob::CodeBlob(const char* name, CompilerType type, const CodeBlobLayout& la
_relocation_end(layout.relocation_end()), _relocation_end(layout.relocation_end()),
_oop_maps(oop_maps), _oop_maps(oop_maps),
_caller_must_gc_arguments(caller_must_gc_arguments), _caller_must_gc_arguments(caller_must_gc_arguments),
_strings(CodeStrings()),
_name(name) _name(name)
NOT_PRODUCT(COMMA _strings(CodeStrings()))
{ {
assert(is_aligned(layout.size(), oopSize), "unaligned size"); assert(is_aligned(layout.size(), oopSize), "unaligned size");
assert(is_aligned(layout.header_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_begin(layout.relocation_begin()),
_relocation_end(layout.relocation_end()), _relocation_end(layout.relocation_end()),
_caller_must_gc_arguments(caller_must_gc_arguments), _caller_must_gc_arguments(caller_must_gc_arguments),
_strings(CodeStrings()),
_name(name) _name(name)
NOT_PRODUCT(COMMA _strings(CodeStrings()))
{ {
assert(is_aligned(_size, oopSize), "unaligned size"); assert(is_aligned(_size, oopSize), "unaligned size");
assert(is_aligned(_header_size, oopSize), "unaligned size"); assert(is_aligned(_header_size, oopSize), "unaligned size");
@ -158,7 +158,7 @@ RuntimeBlob::RuntimeBlob(
void CodeBlob::flush() { void CodeBlob::flush() {
FREE_C_HEAP_ARRAY(unsigned char, _oop_maps); FREE_C_HEAP_ARRAY(unsigned char, _oop_maps);
_oop_maps = NULL; _oop_maps = NULL;
_strings.free(); NOT_PRODUCT(_strings.free();)
} }
void CodeBlob::set_oop_maps(OopMapSet* p) { void CodeBlob::set_oop_maps(OopMapSet* p) {

View file

@ -110,10 +110,12 @@ protected:
ImmutableOopMapSet* _oop_maps; // OopMap for this CodeBlob ImmutableOopMapSet* _oop_maps; // OopMap for this CodeBlob
bool _caller_must_gc_arguments; bool _caller_must_gc_arguments;
CodeStrings _strings;
const char* _name; const char* _name;
S390_ONLY(int _ctable_offset;) 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, 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); 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 dump_for_addr(address addr, outputStream* st, bool verbose) const;
void print_code(); 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 // Print the comment associated with offset on stream, if there is one
virtual void print_block_comment(outputStream* stream, address block_begin) const { virtual void print_block_comment(outputStream* stream, address block_begin) const {
#ifndef PRODUCT
intptr_t offset = (intptr_t)(block_begin - code_begin()); intptr_t offset = (intptr_t)(block_begin - code_begin());
_strings.print_block_comment(stream, offset); _strings.print_block_comment(stream, offset);
#endif
} }
// Transfer ownership of comments to this CodeBlob #ifndef PRODUCT
void set_strings(CodeStrings& strings) { void set_strings(CodeStrings& strings) {
assert(!is_aot(), "invalid on aot"); assert(!is_aot(), "invalid on aot");
_strings.assign(strings); _strings.copy(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);
} }
#endif
}; };
class CodeBlobLayout : public StackObj { class CodeBlobLayout : public StackObj {

View file

@ -695,9 +695,7 @@ public:
CodeBlob::print_block_comment(stream, block_begin); CodeBlob::print_block_comment(stream, block_begin);
#endif #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; void print_nmethod_labels(outputStream* stream, address block_begin, bool print_section_labels=true) const;
const char* nmethod_section_label(address pos) const; const char* nmethod_section_label(address pos) const;

View file

@ -63,7 +63,7 @@ class decode_env {
CodeBuffer* _codeBuffer; // != NULL only when decoding a CodeBuffer CodeBuffer* _codeBuffer; // != NULL only when decoding a CodeBuffer
CodeBlob* _codeBlob; // != NULL only when decoding a CodeBlob CodeBlob* _codeBlob; // != NULL only when decoding a CodeBlob
nmethod* _nm; // != NULL only when decoding a nmethod nmethod* _nm; // != NULL only when decoding a nmethod
CodeStrings _strings;
address _start; // != NULL when decoding a range of unknown type address _start; // != NULL when decoding a range of unknown type
address _end; // != 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 _print_help;
bool _helpPrinted; bool _helpPrinted;
static bool _optionsParsed; static bool _optionsParsed;
NOT_PRODUCT(const CodeStrings* _strings;)
enum { enum {
tabspacing = 8 tabspacing = 8
@ -214,12 +215,11 @@ class decode_env {
} }
public: public:
decode_env(CodeBuffer* code, outputStream* output); decode_env(CodeBlob* code, outputStream* output);
decode_env(CodeBlob* code, outputStream* output, CodeStrings c = CodeStrings() /* , ptrdiff_t offset */); decode_env(nmethod* code, outputStream* output);
decode_env(nmethod* code, outputStream* output, CodeStrings c = CodeStrings());
// Constructor for a 'decode_env' to decode an arbitrary // Constructor for a 'decode_env' to decode an arbitrary
// piece of memory, hopefully containing code. // 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 // Add 'original_start' argument which is the the original address
// the instructions were located at (if this is not equal to 'start'). // 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), _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), _codeBlob(code),
_nm(_codeBlob != NULL && _codeBlob->is_nmethod() ? (nmethod*) code : NULL), _nm(_codeBlob != NULL && _codeBlob->is_nmethod() ? (nmethod*) code : NULL),
_strings(),
_start(NULL), _start(NULL),
_end(NULL), _end(NULL),
_option_buf(), _option_buf(),
@ -360,19 +336,18 @@ decode_env::decode_env(CodeBlob* code, outputStream* output, CodeStrings c) :
_post_decode_alignment(0), _post_decode_alignment(0),
_print_file_name(false), _print_file_name(false),
_print_help(false), _print_help(false),
_helpPrinted(false) { _helpPrinted(false)
NOT_PRODUCT(COMMA _strings(NULL)) {
memset(_option_buf, 0, sizeof(_option_buf)); memset(_option_buf, 0, sizeof(_option_buf));
_strings.copy(c);
process_options(_output); 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), _output(output ? output : tty),
_codeBuffer(NULL),
_codeBlob(NULL), _codeBlob(NULL),
_nm(code), _nm(code),
_strings(),
_start(_nm->code_begin()), _start(_nm->code_begin()),
_end(_nm->code_end()), _end(_nm->code_end()),
_option_buf(), _option_buf(),
@ -383,21 +358,19 @@ decode_env::decode_env(nmethod* code, outputStream* output, CodeStrings c) :
_post_decode_alignment(0), _post_decode_alignment(0),
_print_file_name(false), _print_file_name(false),
_print_help(false), _print_help(false),
_helpPrinted(false) { _helpPrinted(false)
NOT_PRODUCT(COMMA _strings(NULL)) {
memset(_option_buf, 0, sizeof(_option_buf)); memset(_option_buf, 0, sizeof(_option_buf));
_strings.copy(c);
process_options(_output); process_options(_output);
} }
// Constructor for a 'decode_env' to decode a memory range [start, end) // Constructor for a 'decode_env' to decode a memory range [start, end)
// of unknown origin, assuming it contains code. // 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), _output(output ? output : tty),
_codeBuffer(NULL),
_codeBlob(NULL), _codeBlob(NULL),
_nm(NULL), _nm(NULL),
_strings(),
_start(start), _start(start),
_end(end), _end(end),
_option_buf(), _option_buf(),
@ -408,7 +381,8 @@ decode_env::decode_env(address start, address end, outputStream* output) :
_post_decode_alignment(0), _post_decode_alignment(0),
_print_file_name(false), _print_file_name(false),
_print_help(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)); assert(start < end, "Range must have a positive size, [" PTR_FORMAT ".." PTR_FORMAT ").", p2i(start), p2i(end));
memset(_option_buf, 0, sizeof(_option_buf)); memset(_option_buf, 0, sizeof(_option_buf));
@ -682,10 +656,11 @@ void decode_env::print_insn_labels() {
if (_codeBlob != NULL) { if (_codeBlob != NULL) {
_codeBlob->print_block_comment(st, p); _codeBlob->print_block_comment(st, p);
} }
if (_codeBuffer != NULL) { #ifndef PRODUCT
_codeBuffer->print_block_comment(st, p); 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. // 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 defined(SUPPORT_ASSEMBLY) || defined(SUPPORT_ABSTRACT_ASSEMBLY)
if (cb->is_nmethod()) { if (cb->is_nmethod()) {
// If we have an nmethod at hand, // If we have an nmethod at hand,
// call the specialized decoder directly. // call the specialized decoder directly.
decode((nmethod*)cb, st, c); decode((nmethod*)cb, st);
return; return;
} }
@ -999,7 +938,7 @@ void Disassembler::decode(CodeBlob* cb, outputStream* st, CodeStrings c) {
// Decode a nmethod. // Decode a nmethod.
// This includes printing the constant pool and all code segments. // This includes printing the constant pool and all code segments.
// The nmethod data structures (oop maps, relocations and the like) are not printed. // 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) #if defined(SUPPORT_ASSEMBLY) || defined(SUPPORT_ABSTRACT_ASSEMBLY)
ttyLocker ttyl; ttyLocker ttyl;
@ -1018,7 +957,7 @@ void Disassembler::decode(nmethod* nm, outputStream* st, CodeStrings c) {
} }
// Decode a range, given as [start address, end address) // 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) #if defined(SUPPORT_ASSEMBLY) || defined(SUPPORT_ABSTRACT_ASSEMBLY)
//---< Test memory before decoding >--- //---< Test memory before decoding >---
if (!os::is_readable_range(start, end)) { if (!os::is_readable_range(start, end)) {
@ -1046,7 +985,7 @@ void Disassembler::decode(address start, address end, outputStream* st, CodeStri
#endif #endif
{ {
// This seems to be just a chunk of memory. // 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.output()->print_cr("--------------------------------------------------------------------------------");
env.decode_instructions(start, end); env.decode_instructions(start, end);
env.output()->print_cr("--------------------------------------------------------------------------------"); env.output()->print_cr("--------------------------------------------------------------------------------");

View file

@ -28,7 +28,8 @@
#include "utilities/globalDefinitions.hpp" #include "utilities/globalDefinitions.hpp"
#include "asm/assembler.hpp" #include "asm/assembler.hpp"
#include "asm/codeBuffer.hpp" #include "code/codeBlob.hpp"
#include "code/nmethod.hpp"
#include "compiler/abstractDisassembler.hpp" #include "compiler/abstractDisassembler.hpp"
#include "runtime/globals.hpp" #include "runtime/globals.hpp"
#include "utilities/macros.hpp" #include "utilities/macros.hpp"
@ -88,10 +89,10 @@ class Disassembler : public AbstractDisassembler {
// about which decoding format is used. // about which decoding format is used.
// We can also enforce using the abstract disassembler. // We can also enforce using the abstract disassembler.
static bool is_abstract() { static bool is_abstract() {
if (!_tried_to_load_library /* && !UseAbstractDisassembler */) { if (!_tried_to_load_library) {
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 // Check out if we are doing a live disassembly or a post-mortem
@ -105,14 +106,12 @@ class Disassembler : public AbstractDisassembler {
#endif #endif
} }
// Directly disassemble code buffer.
static void decode(CodeBuffer* cb, address start, address end, outputStream* st = NULL);
// Directly disassemble code blob. // 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. // 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. // 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); static void _hook(const char* file, int line, class MacroAssembler* masm);

View file

@ -76,7 +76,7 @@ void InterpreterCodelet::print_on(outputStream* st) const {
if (PrintInterpreter) { if (PrintInterpreter) {
st->cr(); 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. // Commit Codelet.
int committed_code_size = (*_masm)->code()->pure_insts_size(); int committed_code_size = (*_masm)->code()->pure_insts_size();
if (committed_code_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. // Make sure nobody can use _masm outside a CodeletMark lifespan.
*_masm = NULL; *_masm = NULL;

View file

@ -49,14 +49,14 @@ class InterpreterCodelet: public Stub {
int _size; // the size in bytes int _size; // the size in bytes
const char* _description; // a description of the codelet, for debugging & printing const char* _description; // a description of the codelet, for debugging & printing
Bytecodes::Code _bytecode; // associated bytecode if any 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: public:
// Initialization/finalization // Initialization/finalization
void initialize(int size, void initialize(int size,
CodeStrings& strings) { _size = size; CodeStrings& strings) { _size = size;
DEBUG_ONLY(::new(&_strings) CodeStrings();) NOT_PRODUCT(_strings = CodeStrings();)
DEBUG_ONLY(_strings.assign(strings);) } NOT_PRODUCT(_strings.copy(strings);) }
void finalize() { ShouldNotCallThis(); } void finalize() { ShouldNotCallThis(); }
// General info/converters // General info/converters

View file

@ -51,6 +51,7 @@
LOG_TAG(classhisto) \ LOG_TAG(classhisto) \
LOG_TAG(cleanup) \ LOG_TAG(cleanup) \
LOG_TAG(codecache) \ LOG_TAG(codecache) \
NOT_PRODUCT(LOG_TAG(codestrings)) \
LOG_TAG(compaction) \ LOG_TAG(compaction) \
LOG_TAG(compilation) \ LOG_TAG(compilation) \
LOG_TAG(condy) \ LOG_TAG(condy) \

View file

@ -73,13 +73,13 @@ StubCodeGenerator::StubCodeGenerator(CodeBuffer* code, bool print_code) {
} }
StubCodeGenerator::~StubCodeGenerator() { StubCodeGenerator::~StubCodeGenerator() {
if (PRODUCT_ONLY(_print_code) NOT_PRODUCT(true)) { #ifndef PRODUCT
CodeBuffer* cbuf = _masm->code(); CodeBuffer* cbuf = _masm->code();
CodeBlob* blob = CodeCache::find_blob_unsafe(cbuf->insts()->start()); CodeBlob* blob = CodeCache::find_blob_unsafe(cbuf->insts()->start());
if (blob != NULL) { if (blob != NULL) {
blob->set_strings(cbuf->strings()); blob->set_strings(cbuf->strings());
}
} }
#endif
} }
void StubCodeGenerator::stub_prolog(StubCodeDesc* cdesc) { void StubCodeGenerator::stub_prolog(StubCodeDesc* cdesc) {
@ -88,21 +88,16 @@ void StubCodeGenerator::stub_prolog(StubCodeDesc* cdesc) {
void StubCodeGenerator::stub_epilog(StubCodeDesc* cdesc) { void StubCodeGenerator::stub_epilog(StubCodeDesc* cdesc) {
if (_print_code) { if (_print_code) {
CodeStrings cs;
ptrdiff_t offset = 0;
#ifndef PRODUCT #ifndef PRODUCT
// Find the code strings in the outer CodeBuffer. // Find the code strings in the outer CodeBuffer.
CodeBuffer *outer_cbuf = _masm->code_section()->outer(); CodeBuffer *outer_cbuf = _masm->code_section()->outer();
cs = outer_cbuf->strings(); CodeStrings* 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();
#endif #endif
ttyLocker ttyl; ttyLocker ttyl;
tty->print_cr("- - - [BEGIN] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"); tty->print_cr("- - - [BEGIN] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
cdesc->print_on(tty); cdesc->print_on(tty);
tty->cr(); 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->print_cr("- - - [END] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
tty->cr(); tty->cr();
} }