src/share/vm/asm/codeBuffer.cpp

Print this page
rev 4202 : 8008555: Debugging code in compiled method sometimes leaks memory
Summary: support for strings that have same life-time as code that uses them.
Reviewed-by:

*** 701,712 **** CodeBuffer dest(dest_blob); assert(dest_blob->content_size() >= total_content_size(), "good sizing"); this->compute_final_layout(&dest); relocate_code_to(&dest); ! // transfer comments from buffer to blob ! dest_blob->set_comments(_comments); // Done moving code bytes; were they the right size? assert(round_to(dest.total_content_size(), oopSize) == dest_blob->content_size(), "sanity"); // Flush generated code --- 701,712 ---- CodeBuffer dest(dest_blob); assert(dest_blob->content_size() >= total_content_size(), "good sizing"); this->compute_final_layout(&dest); relocate_code_to(&dest); ! // transfer strings and comments from buffer to blob ! dest_blob->set_strings(_strings); // Done moving code bytes; were they the right size? assert(round_to(dest.total_content_size(), oopSize) == dest_blob->content_size(), "sanity"); // Flush generated code
*** 1001,1106 **** Disassembler::decode(start(), end()); } void CodeBuffer::block_comment(intptr_t offset, const char * comment) { ! _comments.add_comment(offset, comment); } ! class CodeComment: public CHeapObj<mtCode> { private: ! friend class CodeComments; intptr_t _offset; - const char * _comment; - CodeComment* _next; ! ~CodeComment() { assert(_next == NULL, "wrong interface for freeing list"); ! os::free((void*)_comment, mtCode); } public: ! CodeComment(intptr_t offset, const char * comment) { ! _offset = offset; ! _comment = os::strdup(comment, mtCode); ! _next = NULL; ! } ! ! intptr_t offset() const { return _offset; } ! const char * comment() const { return _comment; } ! CodeComment* next() { return _next; } ! ! void set_next(CodeComment* next) { _next = next; } ! ! CodeComment* find(intptr_t offset) { ! CodeComment* a = this; ! while (a != NULL && a->_offset != offset) { ! a = a->_next; ! } ! return a; } ! // Convenience for add_comment. ! CodeComment* find_last(intptr_t offset) { ! CodeComment* a = find(offset); ! if (a != NULL) { ! while ((a->_next != NULL) && (a->_next->_offset == offset)) { ! a = a->_next; } } ! return a; } }; ! void CodeComments::add_comment(intptr_t offset, const char * comment) { ! CodeComment* c = new CodeComment(offset, comment); ! CodeComment* inspos = (_comments == NULL) ? NULL : _comments->find_last(offset); if (inspos) { // insert after already existing comments with same offset c->set_next(inspos->next()); inspos->set_next(c); } else { // no comments with such offset, yet. Insert before anything else. ! c->set_next(_comments); ! _comments = c; } } ! ! void CodeComments::assign(CodeComments& other) { ! _comments = other._comments; } ! ! void CodeComments::print_block_comment(outputStream* stream, intptr_t offset) const { ! if (_comments != NULL) { ! CodeComment* c = _comments->find(offset); while (c && c->offset() == offset) { stream->bol(); stream->print(" ;; "); ! stream->print_cr(c->comment()); ! c = c->next(); } } } ! void CodeComments::free() { ! CodeComment* n = _comments; while (n) { // unlink the node from the list saving a pointer to the next ! CodeComment* p = n->_next; ! n->_next = NULL; delete n; n = p; } ! _comments = NULL; } ! void CodeBuffer::decode() { ttyLocker ttyl; Disassembler::decode(decode_begin(), insts_end()); _decode_begin = insts_end(); --- 1001,1129 ---- Disassembler::decode(start(), end()); } void CodeBuffer::block_comment(intptr_t offset, const char * comment) { ! _strings.add_comment(offset, comment); } ! const char* CodeBuffer::code_string(const char* str) { ! return _strings.add_string(str); ! } ! ! class CodeString: public CHeapObj<mtCode> { private: ! friend class CodeStrings; ! const char * _string; ! CodeString* _next; intptr_t _offset; ! ~CodeString() { assert(_next == NULL, "wrong interface for freeing list"); ! os::free((void*)_string, mtCode); } + bool is_comment() const { return _offset >= 0; } + public: ! CodeString(const char * string, intptr_t offset = -1) ! : _next(NULL), _offset(offset) { ! _string = os::strdup(string, mtCode); } ! const char * string() const { return _string; } ! intptr_t offset() const { assert(_offset >= 0, "offset for non comment?"); return _offset; } ! CodeString* next() const { return _next; } ! ! void set_next(CodeString* next) { _next = next; } ! ! CodeString* first_comment() { ! if (is_comment()) { ! return this; ! } else { ! return next_comment(); } } ! CodeString* next_comment() const { ! CodeString* s = _next; ! while (s != NULL && !s->is_comment()) { ! s = s->_next; ! } ! return s; } }; + CodeString* CodeStrings::find(intptr_t offset) const { + CodeString* a = _strings->first_comment(); + while (a != NULL && a->offset() != offset) { + a = a->next_comment(); + } + return a; + } + + // Convenience for add_comment. + CodeString* CodeStrings::find_last(intptr_t offset) const { + CodeString* a = find(offset); + if (a != NULL) { + CodeString* c = NULL; + while (((c = a->next_comment()) != NULL) && (c->offset() == offset)) { + a = c; + } + } + return a; + } ! 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) { // insert after already existing comments with same offset c->set_next(inspos->next()); inspos->set_next(c); } else { // no comments with such offset, yet. Insert before anything else. ! c->set_next(_strings); ! _strings = c; } } ! void CodeStrings::assign(CodeStrings& other) { ! _strings = other._strings; } ! void CodeStrings::print_block_comment(outputStream* stream, intptr_t offset) const { ! if (_strings != NULL) { ! CodeString* c = find(offset); while (c && c->offset() == offset) { stream->bol(); stream->print(" ;; "); ! stream->print_cr(c->string()); ! c = c->next_comment(); } } } ! void CodeStrings::free() { ! CodeString* n = _strings; while (n) { // unlink the node from the list saving a pointer to the next ! CodeString* p = n->next(); ! n->set_next(NULL); delete n; n = p; } ! _strings = NULL; } ! const char* CodeStrings::add_string(const char * string) { ! CodeString* s = new CodeString(string); ! s->set_next(_strings); ! _strings = s; ! return s->string(); ! } void CodeBuffer::decode() { ttyLocker ttyl; Disassembler::decode(decode_begin(), insts_end()); _decode_begin = insts_end();