comparison src/share/vm/asm/codeBuffer.cpp @ 8767:a5de0cc2f91c

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: kvn, twisti
author roland
date Mon, 18 Mar 2013 13:19:06 +0100
parents 30866cd626b0
children b9a918201d47 de6a9e811145
comparison
equal deleted inserted replaced
8765:592f9722c72e 8767:a5de0cc2f91c
701 CodeBuffer dest(dest_blob); 701 CodeBuffer dest(dest_blob);
702 assert(dest_blob->content_size() >= total_content_size(), "good sizing"); 702 assert(dest_blob->content_size() >= total_content_size(), "good sizing");
703 this->compute_final_layout(&dest); 703 this->compute_final_layout(&dest);
704 relocate_code_to(&dest); 704 relocate_code_to(&dest);
705 705
706 // transfer comments from buffer to blob 706 // transfer strings and comments from buffer to blob
707 dest_blob->set_comments(_comments); 707 dest_blob->set_strings(_strings);
708 708
709 // Done moving code bytes; were they the right size? 709 // Done moving code bytes; were they the right size?
710 assert(round_to(dest.total_content_size(), oopSize) == dest_blob->content_size(), "sanity"); 710 assert(round_to(dest.total_content_size(), oopSize) == dest_blob->content_size(), "sanity");
711 711
712 // Flush generated code 712 // Flush generated code
1001 Disassembler::decode(start(), end()); 1001 Disassembler::decode(start(), end());
1002 } 1002 }
1003 1003
1004 1004
1005 void CodeBuffer::block_comment(intptr_t offset, const char * comment) { 1005 void CodeBuffer::block_comment(intptr_t offset, const char * comment) {
1006 _comments.add_comment(offset, comment); 1006 _strings.add_comment(offset, comment);
1007 } 1007 }
1008 1008
1009 class CodeComment: public CHeapObj<mtCode> { 1009 const char* CodeBuffer::code_string(const char* str) {
1010 return _strings.add_string(str);
1011 }
1012
1013 class CodeString: public CHeapObj<mtCode> {
1010 private: 1014 private:
1011 friend class CodeComments; 1015 friend class CodeStrings;
1016 const char * _string;
1017 CodeString* _next;
1012 intptr_t _offset; 1018 intptr_t _offset;
1013 const char * _comment; 1019
1014 CodeComment* _next; 1020 ~CodeString() {
1015
1016 ~CodeComment() {
1017 assert(_next == NULL, "wrong interface for freeing list"); 1021 assert(_next == NULL, "wrong interface for freeing list");
1018 os::free((void*)_comment, mtCode); 1022 os::free((void*)_string, mtCode);
1019 } 1023 }
1024
1025 bool is_comment() const { return _offset >= 0; }
1020 1026
1021 public: 1027 public:
1022 CodeComment(intptr_t offset, const char * comment) { 1028 CodeString(const char * string, intptr_t offset = -1)
1023 _offset = offset; 1029 : _next(NULL), _offset(offset) {
1024 _comment = os::strdup(comment, mtCode); 1030 _string = os::strdup(string, mtCode);
1025 _next = NULL; 1031 }
1026 } 1032
1027 1033 const char * string() const { return _string; }
1028 intptr_t offset() const { return _offset; } 1034 intptr_t offset() const { assert(_offset >= 0, "offset for non comment?"); return _offset; }
1029 const char * comment() const { return _comment; } 1035 CodeString* next() const { return _next; }
1030 CodeComment* next() { return _next; } 1036
1031 1037 void set_next(CodeString* next) { _next = next; }
1032 void set_next(CodeComment* next) { _next = next; } 1038
1033 1039 CodeString* first_comment() {
1034 CodeComment* find(intptr_t offset) { 1040 if (is_comment()) {
1035 CodeComment* a = this; 1041 return this;
1036 while (a != NULL && a->_offset != offset) { 1042 } else {
1037 a = a->_next; 1043 return next_comment();
1038 } 1044 }
1039 return a; 1045 }
1040 } 1046 CodeString* next_comment() const {
1041 1047 CodeString* s = _next;
1042 // Convenience for add_comment. 1048 while (s != NULL && !s->is_comment()) {
1043 CodeComment* find_last(intptr_t offset) { 1049 s = s->_next;
1044 CodeComment* a = find(offset); 1050 }
1045 if (a != NULL) { 1051 return s;
1046 while ((a->_next != NULL) && (a->_next->_offset == offset)) {
1047 a = a->_next;
1048 }
1049 }
1050 return a;
1051 } 1052 }
1052 }; 1053 };
1053 1054
1054 1055 CodeString* CodeStrings::find(intptr_t offset) const {
1055 void CodeComments::add_comment(intptr_t offset, const char * comment) { 1056 CodeString* a = _strings->first_comment();
1056 CodeComment* c = new CodeComment(offset, comment); 1057 while (a != NULL && a->offset() != offset) {
1057 CodeComment* inspos = (_comments == NULL) ? NULL : _comments->find_last(offset); 1058 a = a->next_comment();
1059 }
1060 return a;
1061 }
1062
1063 // Convenience for add_comment.
1064 CodeString* CodeStrings::find_last(intptr_t offset) const {
1065 CodeString* a = find(offset);
1066 if (a != NULL) {
1067 CodeString* c = NULL;
1068 while (((c = a->next_comment()) != NULL) && (c->offset() == offset)) {
1069 a = c;
1070 }
1071 }
1072 return a;
1073 }
1074
1075 void CodeStrings::add_comment(intptr_t offset, const char * comment) {
1076 CodeString* c = new CodeString(comment, offset);
1077 CodeString* inspos = (_strings == NULL) ? NULL : find_last(offset);
1058 1078
1059 if (inspos) { 1079 if (inspos) {
1060 // insert after already existing comments with same offset 1080 // insert after already existing comments with same offset
1061 c->set_next(inspos->next()); 1081 c->set_next(inspos->next());
1062 inspos->set_next(c); 1082 inspos->set_next(c);
1063 } else { 1083 } else {
1064 // no comments with such offset, yet. Insert before anything else. 1084 // no comments with such offset, yet. Insert before anything else.
1065 c->set_next(_comments); 1085 c->set_next(_strings);
1066 _comments = c; 1086 _strings = c;
1067 } 1087 }
1068 } 1088 }
1069 1089
1070 1090 void CodeStrings::assign(CodeStrings& other) {
1071 void CodeComments::assign(CodeComments& other) { 1091 _strings = other._strings;
1072 _comments = other._comments; 1092 }
1073 } 1093
1074 1094 void CodeStrings::print_block_comment(outputStream* stream, intptr_t offset) const {
1075 1095 if (_strings != NULL) {
1076 void CodeComments::print_block_comment(outputStream* stream, intptr_t offset) const { 1096 CodeString* c = find(offset);
1077 if (_comments != NULL) {
1078 CodeComment* c = _comments->find(offset);
1079 while (c && c->offset() == offset) { 1097 while (c && c->offset() == offset) {
1080 stream->bol(); 1098 stream->bol();
1081 stream->print(" ;; "); 1099 stream->print(" ;; ");
1082 stream->print_cr(c->comment()); 1100 stream->print_cr(c->string());
1083 c = c->next(); 1101 c = c->next_comment();
1084 } 1102 }
1085 } 1103 }
1086 } 1104 }
1087 1105
1088 1106
1089 void CodeComments::free() { 1107 void CodeStrings::free() {
1090 CodeComment* n = _comments; 1108 CodeString* n = _strings;
1091 while (n) { 1109 while (n) {
1092 // unlink the node from the list saving a pointer to the next 1110 // unlink the node from the list saving a pointer to the next
1093 CodeComment* p = n->_next; 1111 CodeString* p = n->next();
1094 n->_next = NULL; 1112 n->set_next(NULL);
1095 delete n; 1113 delete n;
1096 n = p; 1114 n = p;
1097 } 1115 }
1098 _comments = NULL; 1116 _strings = NULL;
1099 } 1117 }
1100 1118
1101 1119 const char* CodeStrings::add_string(const char * string) {
1120 CodeString* s = new CodeString(string);
1121 s->set_next(_strings);
1122 _strings = s;
1123 assert(s->string() != NULL, "should have a string");
1124 return s->string();
1125 }
1102 1126
1103 void CodeBuffer::decode() { 1127 void CodeBuffer::decode() {
1104 ttyLocker ttyl; 1128 ttyLocker ttyl;
1105 Disassembler::decode(decode_begin(), insts_end()); 1129 Disassembler::decode(decode_begin(), insts_end());
1106 _decode_begin = insts_end(); 1130 _decode_begin = insts_end();