< prev index next >

src/hotspot/share/asm/codeBuffer.cpp

Print this page

  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "asm/codeBuffer.hpp"
  26 #include "code/compiledIC.hpp"
  27 #include "code/oopRecorder.inline.hpp"
  28 #include "compiler/disassembler.hpp"
  29 #include "logging/log.hpp"
  30 #include "oops/klass.inline.hpp"

  31 #include "oops/methodData.hpp"
  32 #include "oops/oop.inline.hpp"
  33 #include "runtime/icache.hpp"
  34 #include "runtime/safepointVerifiers.hpp"
  35 #include "utilities/align.hpp"
  36 #include "utilities/copy.hpp"
  37 #include "utilities/powerOfTwo.hpp"
  38 #include "utilities/xmlstream.hpp"
  39 
  40 // The structure of a CodeSection:
  41 //
  42 //    _start ->           +----------------+
  43 //                        | machine code...|
  44 //    _end ->             |----------------|
  45 //                        |                |
  46 //                        |    (empty)     |
  47 //                        |                |
  48 //                        |                |
  49 //                        +----------------+
  50 //    _limit ->           |                |

 519 void CodeBuffer::finalize_oop_references(const methodHandle& mh) {
 520   NoSafepointVerifier nsv;
 521 
 522   GrowableArray<oop> oops;
 523 
 524   // Make sure that immediate metadata records something in the OopRecorder
 525   for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) {
 526     // pull code out of each section
 527     CodeSection* cs = code_section(n);
 528     if (cs->is_empty() || (cs->locs_count() == 0)) continue;  // skip trivial section
 529     RelocIterator iter(cs);
 530     while (iter.next()) {
 531       if (iter.type() == relocInfo::metadata_type) {
 532         metadata_Relocation* md = iter.metadata_reloc();
 533         if (md->metadata_is_immediate()) {
 534           Metadata* m = md->metadata_value();
 535           if (oop_recorder()->is_real(m)) {
 536             if (m->is_methodData()) {
 537               m = ((MethodData*)m)->method();
 538             }



 539             if (m->is_method()) {
 540               m = ((Method*)m)->method_holder();
 541             }
 542             if (m->is_klass()) {
 543               append_oop_references(&oops, (Klass*)m);
 544             } else {
 545               // XXX This will currently occur for MDO which don't
 546               // have a backpointer.  This has to be fixed later.
 547               m->print();
 548               ShouldNotReachHere();
 549             }
 550           }
 551         }
 552       }
 553     }
 554   }
 555 
 556   if (!oop_recorder()->is_unused()) {
 557     for (int i = 0; i < oop_recorder()->metadata_count(); i++) {
 558       Metadata* m = oop_recorder()->metadata_at(i);
 559       if (oop_recorder()->is_real(m)) {
 560         if (m->is_methodData()) {
 561           m = ((MethodData*)m)->method();
 562         }



 563         if (m->is_method()) {
 564           m = ((Method*)m)->method_holder();
 565         }
 566         if (m->is_klass()) {
 567           append_oop_references(&oops, (Klass*)m);
 568         } else {
 569           m->print();
 570           ShouldNotReachHere();
 571         }
 572       }
 573     }
 574 
 575   }
 576 
 577   // Add the class loader of Method* for the nmethod itself
 578   append_oop_references(&oops, mh->method_holder());
 579 
 580   // Add any oops that we've found
 581   Thread* thread = Thread::current();
 582   for (int i = 0; i < oops.length(); i++) {

 985   address tend   = tstart + _total_size;
 986   if (_blob != nullptr) {
 987     guarantee(tstart >= _blob->content_begin(), "sanity");
 988     guarantee(tend   <= _blob->content_end(),   "sanity");
 989   }
 990   // Verify disjointness.
 991   for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) {
 992     CodeSection* sect = code_section(n);
 993     if (!sect->is_allocated() || sect->is_empty()) {
 994       continue;
 995     }
 996     guarantee(_blob == nullptr || is_aligned(sect->start(), sect->alignment()),
 997            "start is aligned");
 998     for (int m = n + 1; m < (int) SECT_LIMIT; m++) {
 999       CodeSection* other = code_section(m);
1000       if (!other->is_allocated() || other == sect) {
1001         continue;
1002       }
1003       guarantee(other->disjoint(sect), "sanity");
1004     }
1005     guarantee(sect->end() <= tend, "sanity");
1006     guarantee(sect->end() <= sect->limit(), "sanity");
1007   }
1008 }
1009 
1010 void CodeBuffer::log_section_sizes(const char* name) {
1011   if (xtty != nullptr) {
1012     ttyLocker ttyl;
1013     // log info about buffer usage
1014     xtty->print_cr("<blob name='%s' total_size='%d'>", name, _total_size);
1015     for (int n = (int) CodeBuffer::SECT_FIRST; n < (int) CodeBuffer::SECT_LIMIT; n++) {
1016       CodeSection* sect = code_section(n);
1017       if (!sect->is_allocated() || sect->is_empty())  continue;
1018       xtty->print_cr("<sect index='%d' capacity='%d' size='%d' remaining='%d'/>",
1019                      n, sect->capacity(), sect->size(), sect->remaining());
1020     }
1021     xtty->print_cr("</blob>");
1022   }
1023 }
1024 
1025 bool CodeBuffer::finalize_stubs() {
1026   if (_finalize_stubs && !pd_finalize_stubs()) {
1027     // stub allocation failure
1028     return false;
1029   }
1030   _finalize_stubs = false;
1031   return true;
1032 }
1033 
1034 void CodeBuffer::shared_stub_to_interp_for(ciMethod* callee, csize_t call_offset) {
1035   if (_shared_stub_to_interp_requests == nullptr) {
1036     _shared_stub_to_interp_requests = new SharedStubToInterpRequests(8);
1037   }
1038   SharedStubToInterpRequest request(callee, call_offset);
1039   _shared_stub_to_interp_requests->push(request);
1040   _finalize_stubs = true;
1041 }

1070   csize_t locs_size = locs_end() - locs_start();
1071   st->print_cr(" %7s.code = " PTR_FORMAT " : " PTR_FORMAT " : " PTR_FORMAT " (%d of %d)",
1072                 name, p2i(start()), p2i(end()), p2i(limit()), size(), capacity());
1073   st->print_cr(" %7s.locs = " PTR_FORMAT " : " PTR_FORMAT " : " PTR_FORMAT " (%d of %d) point=%d",
1074                 name, p2i(locs_start()), p2i(locs_end()), p2i(locs_limit()), locs_size, locs_capacity(), locs_point_off());
1075   if (PrintRelocations && (locs_size != 0)) {
1076     RelocIterator iter(this);
1077     iter.print_on(st);
1078   }
1079 }
1080 
1081 void CodeBuffer::print_on(outputStream* st) {
1082   st->print_cr("CodeBuffer:%s", name());
1083   for (int n = 0; n < (int)SECT_LIMIT; n++) {
1084     // print each section
1085     CodeSection* cs = code_section(n);
1086     cs->print_on(st, code_section_name(n));
1087   }
1088 }
1089 
1090 // ----- CHeapString -----------------------------------------------------------
1091 
1092 class CHeapString : public CHeapObj<mtCode> {
1093  public:
1094   CHeapString(const char* str) : _string(os::strdup(str)) {}
1095  ~CHeapString() {
1096     os::free((void*)_string);
1097     _string = nullptr;
1098   }
1099   const char* string() const { return _string; }
1100 
1101  private:
1102   const char* _string;
1103 };
1104 
1105 // ----- AsmRemarkCollection ---------------------------------------------------
1106 
1107 class AsmRemarkCollection : public CHeapObj<mtCode> {
1108  public:
1109   AsmRemarkCollection() : _ref_cnt(1), _remarks(nullptr), _next(nullptr) {}
1110  ~AsmRemarkCollection() {
1111     assert(is_empty(), "Must 'clear()' before deleting!");
1112     assert(_ref_cnt == 0, "No uses must remain when deleting!");
1113   }
1114   AsmRemarkCollection* reuse() {
1115     precond(_ref_cnt > 0);
1116     return _ref_cnt++, this;
1117   }
1118 
1119   const char* insert(uint offset, const char* remark);
1120   const char* lookup(uint offset) const;
1121   const char* next(uint offset) const;
1122 
1123   bool is_empty() const { return _remarks == nullptr; }
1124   uint clear();
1125 
1126  private:
1127   struct Cell : CHeapString {
1128     Cell(const char* remark, uint offset) :
1129         CHeapString(remark), offset(offset), prev(nullptr), next(nullptr) {}
1130     void push_back(Cell* cell) {
1131       Cell* head = this;
1132       Cell* tail = prev;
1133       tail->next = cell;
1134       cell->next = head;
1135       cell->prev = tail;
1136       prev = cell;
1137     }
1138     uint offset;
1139     Cell* prev;
1140     Cell* next;
1141   };
1142   uint  _ref_cnt;
1143   Cell* _remarks;
1144   // Using a 'mutable' iteration pointer to allow 'const' on lookup/next (that
1145   // does not change the state of the list per se), supportig a simplistic
1146   // iteration scheme.
1147   mutable Cell* _next;
1148 };
1149 
1150 // ----- DbgStringCollection ---------------------------------------------------
1151 
1152 class DbgStringCollection : public CHeapObj<mtCode> {
1153  public:
1154   DbgStringCollection() : _ref_cnt(1), _strings(nullptr) {}
1155  ~DbgStringCollection() {
1156     assert(is_empty(), "Must 'clear()' before deleting!");
1157     assert(_ref_cnt == 0, "No uses must remain when deleting!");
1158   }
1159   DbgStringCollection* reuse() {
1160     precond(_ref_cnt > 0);
1161     return _ref_cnt++, this;
1162   }
1163 
1164   const char* insert(const char* str);
1165   const char* lookup(const char* str) const;
1166 
1167   bool is_empty() const { return _strings == nullptr; }
1168   uint clear();
1169 
1170  private:
1171   struct Cell : CHeapString {
1172     Cell(const char* dbgstr) :
1173         CHeapString(dbgstr), prev(nullptr), next(nullptr) {}
1174     void push_back(Cell* cell) {
1175       Cell* head = this;
1176       Cell* tail = prev;
1177       tail->next = cell;
1178       cell->next = head;
1179       cell->prev = tail;
1180       prev = cell;
1181     }
1182     Cell* prev;
1183     Cell* next;
1184   };
1185   uint  _ref_cnt;
1186   Cell* _strings;
1187 };
1188 
1189 // ----- AsmRemarks ------------------------------------------------------------
1190 //
1191 // Acting as interface to reference counted mapping [offset -> remark], where
1192 // offset is a byte offset into an instruction stream (CodeBuffer, CodeBlob or
1193 // other memory buffer) and remark is a string (comment).
1194 //
1195 AsmRemarks::AsmRemarks() : _remarks(new AsmRemarkCollection()) {
1196   assert(_remarks != nullptr, "Allocation failure!");
1197 }
1198 
1199 AsmRemarks::~AsmRemarks() {



1200   assert(_remarks == nullptr, "Must 'clear()' before deleting!");
1201 }
1202 




1203 const char* AsmRemarks::insert(uint offset, const char* remstr) {
1204   precond(remstr != nullptr);
1205   return _remarks->insert(offset, remstr);
1206 }
1207 
1208 bool AsmRemarks::is_empty() const {
1209   return _remarks->is_empty();
1210 }
1211 
1212 void AsmRemarks::share(const AsmRemarks &src) {
1213   precond(is_empty());
1214   clear();
1215   _remarks = src._remarks->reuse();
1216 }
1217 
1218 void AsmRemarks::clear() {

1219   if (_remarks->clear() == 0) {
1220     delete _remarks;
1221   }
1222   _remarks = nullptr;
1223 }
1224 
1225 uint AsmRemarks::print(uint offset, outputStream* strm) const {
1226   uint count = 0;
1227   const char* prefix = " ;; ";
1228   const char* remstr = _remarks->lookup(offset);
1229   while (remstr != nullptr) {
1230     strm->bol();
1231     strm->print("%s", prefix);
1232     // Don't interpret as format strings since it could contain '%'.
1233     strm->print_raw(remstr);
1234     // Advance to next line iff string didn't contain a cr() at the end.
1235     strm->bol();
1236     remstr = _remarks->next(offset);
1237     count++;
1238   }
1239   return count;
1240 }
1241 
1242 // ----- DbgStrings ------------------------------------------------------------
1243 //
1244 // Acting as interface to reference counted collection of (debug) strings used
1245 // in the code generated, and thus requiring a fixed address.
1246 //
1247 DbgStrings::DbgStrings() : _strings(new DbgStringCollection()) {
1248   assert(_strings != nullptr, "Allocation failure!");
1249 }
1250 
1251 DbgStrings::~DbgStrings() {



1252   assert(_strings == nullptr, "Must 'clear()' before deleting!");
1253 }
1254 




1255 const char* DbgStrings::insert(const char* dbgstr) {
1256   const char* str = _strings->lookup(dbgstr);
1257   return str != nullptr ? str : _strings->insert(dbgstr);
1258 }
1259 
1260 bool DbgStrings::is_empty() const {
1261   return _strings->is_empty();
1262 }
1263 
1264 void DbgStrings::share(const DbgStrings &src) {
1265   precond(is_empty());
1266   clear();
1267   _strings = src._strings->reuse();
1268 }
1269 
1270 void DbgStrings::clear() {

1271   if (_strings->clear() == 0) {
1272     delete _strings;
1273   }
1274   _strings = nullptr;
1275 }
1276 
1277 // ----- AsmRemarkCollection ---------------------------------------------------
1278 
1279 const char* AsmRemarkCollection::insert(uint offset, const char* remstr) {
1280   precond(remstr != nullptr);
1281   Cell* cell = new Cell { remstr, offset };
1282   if (is_empty()) {
1283     cell->prev = cell;
1284     cell->next = cell;
1285     _remarks = cell;
1286   } else {
1287     _remarks->push_back(cell);
1288   }
1289   return cell->string();
1290 }

  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "asm/codeBuffer.hpp"
  26 #include "code/compiledIC.hpp"
  27 #include "code/oopRecorder.inline.hpp"
  28 #include "compiler/disassembler.hpp"
  29 #include "logging/log.hpp"
  30 #include "oops/klass.inline.hpp"
  31 #include "oops/methodCounters.hpp"
  32 #include "oops/methodData.hpp"
  33 #include "oops/oop.inline.hpp"
  34 #include "runtime/icache.hpp"
  35 #include "runtime/safepointVerifiers.hpp"
  36 #include "utilities/align.hpp"
  37 #include "utilities/copy.hpp"
  38 #include "utilities/powerOfTwo.hpp"
  39 #include "utilities/xmlstream.hpp"
  40 
  41 // The structure of a CodeSection:
  42 //
  43 //    _start ->           +----------------+
  44 //                        | machine code...|
  45 //    _end ->             |----------------|
  46 //                        |                |
  47 //                        |    (empty)     |
  48 //                        |                |
  49 //                        |                |
  50 //                        +----------------+
  51 //    _limit ->           |                |

 520 void CodeBuffer::finalize_oop_references(const methodHandle& mh) {
 521   NoSafepointVerifier nsv;
 522 
 523   GrowableArray<oop> oops;
 524 
 525   // Make sure that immediate metadata records something in the OopRecorder
 526   for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) {
 527     // pull code out of each section
 528     CodeSection* cs = code_section(n);
 529     if (cs->is_empty() || (cs->locs_count() == 0)) continue;  // skip trivial section
 530     RelocIterator iter(cs);
 531     while (iter.next()) {
 532       if (iter.type() == relocInfo::metadata_type) {
 533         metadata_Relocation* md = iter.metadata_reloc();
 534         if (md->metadata_is_immediate()) {
 535           Metadata* m = md->metadata_value();
 536           if (oop_recorder()->is_real(m)) {
 537             if (m->is_methodData()) {
 538               m = ((MethodData*)m)->method();
 539             }
 540             if (m->is_methodCounters()) {
 541               m = ((MethodCounters*)m)->method();
 542             }
 543             if (m->is_method()) {
 544               m = ((Method*)m)->method_holder();
 545             }
 546             if (m->is_klass()) {
 547               append_oop_references(&oops, (Klass*)m);
 548             } else {
 549               // XXX This will currently occur for MDO which don't
 550               // have a backpointer.  This has to be fixed later.
 551               m->print();
 552               ShouldNotReachHere();
 553             }
 554           }
 555         }
 556       }
 557     }
 558   }
 559 
 560   if (!oop_recorder()->is_unused()) {
 561     for (int i = 0; i < oop_recorder()->metadata_count(); i++) {
 562       Metadata* m = oop_recorder()->metadata_at(i);
 563       if (oop_recorder()->is_real(m)) {
 564         if (m->is_methodData()) {
 565           m = ((MethodData*)m)->method();
 566         }
 567         if (m->is_methodCounters()) {
 568           m = ((MethodCounters*)m)->method();
 569         }
 570         if (m->is_method()) {
 571           m = ((Method*)m)->method_holder();
 572         }
 573         if (m->is_klass()) {
 574           append_oop_references(&oops, (Klass*)m);
 575         } else {
 576           m->print();
 577           ShouldNotReachHere();
 578         }
 579       }
 580     }
 581 
 582   }
 583 
 584   // Add the class loader of Method* for the nmethod itself
 585   append_oop_references(&oops, mh->method_holder());
 586 
 587   // Add any oops that we've found
 588   Thread* thread = Thread::current();
 589   for (int i = 0; i < oops.length(); i++) {

 992   address tend   = tstart + _total_size;
 993   if (_blob != nullptr) {
 994     guarantee(tstart >= _blob->content_begin(), "sanity");
 995     guarantee(tend   <= _blob->content_end(),   "sanity");
 996   }
 997   // Verify disjointness.
 998   for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) {
 999     CodeSection* sect = code_section(n);
1000     if (!sect->is_allocated() || sect->is_empty()) {
1001       continue;
1002     }
1003     guarantee(_blob == nullptr || is_aligned(sect->start(), sect->alignment()),
1004            "start is aligned");
1005     for (int m = n + 1; m < (int) SECT_LIMIT; m++) {
1006       CodeSection* other = code_section(m);
1007       if (!other->is_allocated() || other == sect) {
1008         continue;
1009       }
1010       guarantee(other->disjoint(sect), "sanity");
1011     }
1012     guarantee(sect->end() <= tend, "sanity, sect_end: " PTR_FORMAT " tend: " PTR_FORMAT " size: %d", p2i(sect->end()), p2i(tend), (int)_total_size);
1013     guarantee(sect->end() <= sect->limit(), "sanity, sect_end: " PTR_FORMAT " sect_limit: " PTR_FORMAT, p2i(sect->end()), p2i(sect->limit()));
1014   }
1015 }
1016 
1017 void CodeBuffer::log_section_sizes(const char* name) {
1018   if (xtty != nullptr) {
1019     ttyLocker ttyl;
1020     // log info about buffer usage
1021     xtty->head("blob name='%s' total_size='%d'", name, _total_size);
1022     for (int n = (int) CodeBuffer::SECT_FIRST; n < (int) CodeBuffer::SECT_LIMIT; n++) {
1023       CodeSection* sect = code_section(n);
1024       if (!sect->is_allocated() || sect->is_empty())  continue;
1025       xtty->elem("sect index='%d' capacity='%d' size='%d' remaining='%d'",
1026                  n, sect->capacity(), sect->size(), sect->remaining());
1027     }
1028     xtty->tail("blob");
1029   }
1030 }
1031 
1032 bool CodeBuffer::finalize_stubs() {
1033   if (_finalize_stubs && !pd_finalize_stubs()) {
1034     // stub allocation failure
1035     return false;
1036   }
1037   _finalize_stubs = false;
1038   return true;
1039 }
1040 
1041 void CodeBuffer::shared_stub_to_interp_for(ciMethod* callee, csize_t call_offset) {
1042   if (_shared_stub_to_interp_requests == nullptr) {
1043     _shared_stub_to_interp_requests = new SharedStubToInterpRequests(8);
1044   }
1045   SharedStubToInterpRequest request(callee, call_offset);
1046   _shared_stub_to_interp_requests->push(request);
1047   _finalize_stubs = true;
1048 }

1077   csize_t locs_size = locs_end() - locs_start();
1078   st->print_cr(" %7s.code = " PTR_FORMAT " : " PTR_FORMAT " : " PTR_FORMAT " (%d of %d)",
1079                 name, p2i(start()), p2i(end()), p2i(limit()), size(), capacity());
1080   st->print_cr(" %7s.locs = " PTR_FORMAT " : " PTR_FORMAT " : " PTR_FORMAT " (%d of %d) point=%d",
1081                 name, p2i(locs_start()), p2i(locs_end()), p2i(locs_limit()), locs_size, locs_capacity(), locs_point_off());
1082   if (PrintRelocations && (locs_size != 0)) {
1083     RelocIterator iter(this);
1084     iter.print_on(st);
1085   }
1086 }
1087 
1088 void CodeBuffer::print_on(outputStream* st) {
1089   st->print_cr("CodeBuffer:%s", name());
1090   for (int n = 0; n < (int)SECT_LIMIT; n++) {
1091     // print each section
1092     CodeSection* cs = code_section(n);
1093     cs->print_on(st, code_section_name(n));
1094   }
1095 }
1096 



































































































1097 // ----- AsmRemarks ------------------------------------------------------------
1098 //
1099 // Acting as interface to reference counted mapping [offset -> remark], where
1100 // offset is a byte offset into an instruction stream (CodeBuffer, CodeBlob or
1101 // other memory buffer) and remark is a string (comment).
1102 //
1103 AsmRemarks::AsmRemarks() : _remarks(new AsmRemarkCollection()) {
1104   assert(_remarks != nullptr, "Allocation failure!");
1105 }
1106 
1107 AsmRemarks::~AsmRemarks() {
1108   if (_remarks != nullptr) {
1109     clear();
1110   }
1111   assert(_remarks == nullptr, "Must 'clear()' before deleting!");
1112 }
1113 
1114 void AsmRemarks::init(AsmRemarks& asm_remarks) {
1115   asm_remarks._remarks = new AsmRemarkCollection();
1116 }
1117 
1118 const char* AsmRemarks::insert(uint offset, const char* remstr) {
1119   precond(remstr != nullptr);
1120   return _remarks->insert(offset, remstr);
1121 }
1122 
1123 bool AsmRemarks::is_empty() const {
1124   return _remarks->is_empty();
1125 }
1126 
1127 void AsmRemarks::share(const AsmRemarks &src) {
1128   precond(is_empty());
1129   clear();
1130   _remarks = src._remarks->reuse();
1131 }
1132 
1133 void AsmRemarks::clear() {
1134   assert(_remarks != nullptr, "sanity check");
1135   if (_remarks->clear() == 0) {
1136     delete _remarks;
1137   }
1138   _remarks = nullptr;
1139 }
1140 
1141 uint AsmRemarks::print(uint offset, outputStream* strm) const {
1142   uint count = 0;
1143   const char* prefix = " ;; ";
1144   const char* remstr = _remarks->lookup(offset);
1145   while (remstr != nullptr) {
1146     strm->bol();
1147     strm->print("%s", prefix);
1148     // Don't interpret as format strings since it could contain '%'.
1149     strm->print_raw(remstr);
1150     // Advance to next line iff string didn't contain a cr() at the end.
1151     strm->bol();
1152     remstr = _remarks->next(offset);
1153     count++;
1154   }
1155   return count;
1156 }
1157 
1158 // ----- DbgStrings ------------------------------------------------------------
1159 //
1160 // Acting as interface to reference counted collection of (debug) strings used
1161 // in the code generated, and thus requiring a fixed address.
1162 //
1163 DbgStrings::DbgStrings() : _strings(new DbgStringCollection()) {
1164   assert(_strings != nullptr, "Allocation failure!");
1165 }
1166 
1167 DbgStrings::~DbgStrings() {
1168   if (_strings != nullptr) {
1169     clear();
1170   }
1171   assert(_strings == nullptr, "Must 'clear()' before deleting!");
1172 }
1173 
1174 void DbgStrings::init(DbgStrings& dbg_strings) {
1175   dbg_strings._strings = new DbgStringCollection();
1176 }
1177 
1178 const char* DbgStrings::insert(const char* dbgstr) {
1179   const char* str = _strings->lookup(dbgstr);
1180   return str != nullptr ? str : _strings->insert(dbgstr);
1181 }
1182 
1183 bool DbgStrings::is_empty() const {
1184   return _strings->is_empty();
1185 }
1186 
1187 void DbgStrings::share(const DbgStrings &src) {
1188   precond(is_empty());
1189   clear();
1190   _strings = src._strings->reuse();
1191 }
1192 
1193 void DbgStrings::clear() {
1194   assert(_strings != nullptr, "sanity check");
1195   if (_strings->clear() == 0) {
1196     delete _strings;
1197   }
1198   _strings = nullptr;
1199 }
1200 
1201 // ----- AsmRemarkCollection ---------------------------------------------------
1202 
1203 const char* AsmRemarkCollection::insert(uint offset, const char* remstr) {
1204   precond(remstr != nullptr);
1205   Cell* cell = new Cell { remstr, offset };
1206   if (is_empty()) {
1207     cell->prev = cell;
1208     cell->next = cell;
1209     _remarks = cell;
1210   } else {
1211     _remarks->push_back(cell);
1212   }
1213   return cell->string();
1214 }
< prev index next >