1 /*
2 * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
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/aotCodeCache.hpp"
27 #include "code/compiledIC.hpp"
28 #include "code/oopRecorder.inline.hpp"
29 #include "compiler/disassembler.hpp"
30 #include "logging/log.hpp"
31 #include "oops/klass.inline.hpp"
32 #include "oops/methodCounters.hpp"
33 #include "oops/methodData.hpp"
34 #include "oops/oop.inline.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 -> | |
52 //
53 // _locs_start -> +----------------+
54 // |reloc records...|
55 // |----------------|
56 // _locs_end -> | |
57 // | |
58 // | (empty) |
59 // | |
60 // | |
61 // +----------------+
62 // _locs_limit -> | |
63 // The _end (resp. _limit) pointer refers to the first
64 // unused (resp. unallocated) byte.
65
66 // The structure of the CodeBuffer while code is being accumulated:
67 //
68 // _total_start -> \
69 // _consts._start -> +----------------+
70 // | |
71 // | Constants |
72 // | |
73 // _insts._start -> |----------------|
74 // | |
75 // | Code |
76 // | |
77 // _stubs._start -> |----------------|
78 // | |
79 // | Stubs | (also handlers for deopt/exception)
80 // | |
81 // +----------------+
82 // + _total_size -> | |
83 //
84 // When the code and relocations are copied to the code cache,
85 // the empty parts of each section are removed, and everything
86 // is copied into contiguous locations.
87
88 typedef CodeBuffer::csize_t csize_t; // file-local definition
89
90 // External buffer, in a predefined CodeBlob.
91 // Important: The code_start must be taken exactly, and not realigned.
92 CodeBuffer::CodeBuffer(const CodeBlob* blob) DEBUG_ONLY(: Scrubber(this, sizeof(*this))) {
93 // Provide code buffer with meaningful name
94 initialize_misc(blob->name());
95 initialize(blob->content_begin(), blob->content_size());
96 DEBUG_ONLY(verify_section_allocation();)
97 }
98
99 void CodeBuffer::initialize(csize_t code_size, csize_t locs_size) {
100 MACOS_AARCH64_ONLY(os::thread_wx_enable_write());
101
102 // Always allow for empty slop around each section.
103 int slop = (int) CodeSection::end_slop();
104
105 assert(SECT_LIMIT == 3, "total_size explicitly lists all section alignments");
106 int total_size = code_size + _consts.alignment() + _insts.alignment() + _stubs.alignment() + SECT_LIMIT * slop;
107
108 assert(blob() == nullptr, "only once");
109 set_blob(BufferBlob::create(_name, total_size));
110 if (blob() == nullptr) {
111 // The assembler constructor will throw a fatal on an empty CodeBuffer.
112 return; // caller must test this
113 }
114
115 // Set up various pointers into the blob.
116 initialize(_total_start, _total_size);
117
118 assert((uintptr_t)insts_begin() % CodeEntryAlignment == 0, "instruction start not code entry aligned");
119
120 pd_initialize();
121
122 if (locs_size != 0) {
123 _insts.initialize_locs(locs_size / sizeof(relocInfo));
124 }
125
126 DEBUG_ONLY(verify_section_allocation();)
127 }
128
129
130 CodeBuffer::~CodeBuffer() {
131 verify_section_allocation();
132
133 // If we allocated our code buffer from the CodeCache via a BufferBlob, and
134 // it's not permanent, then free the BufferBlob. The rest of the memory
135 // will be freed when the ResourceObj is released.
136 for (CodeBuffer* cb = this; cb != nullptr; cb = cb->before_expand()) {
137 // Previous incarnations of this buffer are held live, so that internal
138 // addresses constructed before expansions will not be confused.
139 cb->free_blob();
140 }
141 if (_overflow_arena != nullptr) {
142 // free any overflow storage
143 delete _overflow_arena;
144 }
145 if (_shared_trampoline_requests != nullptr) {
146 delete _shared_trampoline_requests;
147 }
148
149 NOT_PRODUCT(clear_strings());
150 }
151
152 void CodeBuffer::initialize_oop_recorder(OopRecorder* r) {
153 assert(_oop_recorder == &_default_oop_recorder && _default_oop_recorder.is_unused(), "do this once");
154 DEBUG_ONLY(_default_oop_recorder.freeze()); // force unused OR to be frozen
155 _oop_recorder = r;
156 }
157
158 void CodeBuffer::initialize_section_size(CodeSection* cs, csize_t size) {
159 assert(cs != &_insts, "insts is the memory provider, not the consumer");
160 csize_t slop = CodeSection::end_slop(); // margin between sections
161 int align = cs->alignment();
162 assert(is_power_of_2(align), "sanity");
163 address start = _insts._start;
164 address limit = _insts._limit;
165 address middle = limit - size;
166 middle -= (intptr_t)middle & (align-1); // align the division point downward
167 guarantee(middle - slop > start, "need enough space to divide up");
168 _insts._limit = middle - slop; // subtract desired space, plus slop
169 cs->initialize(middle, limit - middle);
170 assert(cs->start() == middle, "sanity");
171 assert(cs->limit() == limit, "sanity");
172 // give it some relocations to start with, if the main section has them
173 if (_insts.has_locs()) cs->initialize_locs(1);
174 }
175
176 void CodeBuffer::set_blob(BufferBlob* blob) {
177 _blob = blob;
178 if (blob != nullptr) {
179 address start = blob->content_begin();
180 address end = blob->content_end();
181 // Round up the starting address.
182 int align = _insts.alignment();
183 start += (-(intptr_t)start) & (align-1);
184 _total_start = start;
185 _total_size = end - start;
186 } else {
187 #ifdef ASSERT
188 // Clean out dangling pointers.
189 _total_start = badAddress;
190 _consts._start = _consts._end = badAddress;
191 _insts._start = _insts._end = badAddress;
192 _stubs._start = _stubs._end = badAddress;
193 #endif //ASSERT
194 }
195 }
196
197 void CodeBuffer::free_blob() {
198 if (_blob != nullptr) {
199 BufferBlob::free(_blob);
200 set_blob(nullptr);
201 }
202 }
203
204 const char* CodeBuffer::code_section_name(int n) {
205 #ifdef PRODUCT
206 return nullptr;
207 #else //PRODUCT
208 switch (n) {
209 case SECT_CONSTS: return "consts";
210 case SECT_INSTS: return "insts";
211 case SECT_STUBS: return "stubs";
212 default: return nullptr;
213 }
214 #endif //PRODUCT
215 }
216
217 int CodeBuffer::section_index_of(address addr) const {
218 for (int n = 0; n < (int)SECT_LIMIT; n++) {
219 const CodeSection* cs = code_section(n);
220 if (cs->allocates(addr)) return n;
221 }
222 return SECT_NONE;
223 }
224
225 int CodeBuffer::locator(address addr) const {
226 for (int n = 0; n < (int)SECT_LIMIT; n++) {
227 const CodeSection* cs = code_section(n);
228 if (cs->allocates(addr)) {
229 return locator(addr - cs->start(), n);
230 }
231 }
232 return -1;
233 }
234
235
236 bool CodeBuffer::is_backward_branch(Label& L) {
237 return L.is_bound() && insts_end() <= locator_address(L.loc());
238 }
239
240 #ifndef PRODUCT
241 address CodeBuffer::decode_begin() {
242 address begin = _insts.start();
243 if (_decode_begin != nullptr && _decode_begin > begin)
244 begin = _decode_begin;
245 return begin;
246 }
247 #endif // !PRODUCT
248
249 GrowableArray<int>* CodeBuffer::create_patch_overflow() {
250 if (_overflow_arena == nullptr) {
251 _overflow_arena = new (mtCode) Arena(mtCode);
252 }
253 return new (_overflow_arena) GrowableArray<int>(_overflow_arena, 8, 0, 0);
254 }
255
256
257 // Helper function for managing labels and their target addresses.
258 // Returns a sensible address, and if it is not the label's final
259 // address, notes the dependency (at 'branch_pc') on the label.
260 address CodeSection::target(Label& L, address branch_pc) {
261 if (L.is_bound()) {
262 int loc = L.loc();
263 if (index() == CodeBuffer::locator_sect(loc)) {
264 return start() + CodeBuffer::locator_pos(loc);
265 } else {
266 return outer()->locator_address(loc);
267 }
268 } else {
269 assert(allocates2(branch_pc), "sanity");
270 address base = start();
271 int patch_loc = CodeBuffer::locator(branch_pc - base, index());
272 L.add_patch_at(outer(), patch_loc);
273
274 // Need to return a pc, doesn't matter what it is since it will be
275 // replaced during resolution later.
276 // Don't return null or badAddress, since branches shouldn't overflow.
277 // Don't return base either because that could overflow displacements
278 // for shorter branches. It will get checked when bound.
279 return branch_pc;
280 }
281 }
282
283 void CodeSection::relocate(address at, relocInfo::relocType rtype, int format, jint method_index) {
284 RelocationHolder rh;
285 switch (rtype) {
286 case relocInfo::none: return;
287 case relocInfo::opt_virtual_call_type: {
288 rh = opt_virtual_call_Relocation::spec(method_index);
289 break;
290 }
291 case relocInfo::static_call_type: {
292 rh = static_call_Relocation::spec(method_index);
293 break;
294 }
295 case relocInfo::virtual_call_type: {
296 assert(method_index == 0, "resolved method overriding is not supported");
297 rh = Relocation::spec_simple(rtype);
298 break;
299 }
300 default: {
301 rh = Relocation::spec_simple(rtype);
302 break;
303 }
304 }
305 relocate(at, rh, format);
306 }
307
308 void CodeSection::relocate(address at, RelocationHolder const& spec, int format) {
309 // Do not relocate in scratch buffers.
310 if (scratch_emit()) { return; }
311 Relocation* reloc = spec.reloc();
312 relocInfo::relocType rtype = (relocInfo::relocType) reloc->type();
313 if (rtype == relocInfo::none) return;
314
315 // The assertion below has been adjusted, to also work for
316 // relocation for fixup. Sometimes we want to put relocation
317 // information for the next instruction, since it will be patched
318 // with a call.
319 assert(start() <= at && at <= end()+1,
320 "cannot relocate data outside code boundaries");
321
322 if (!has_locs()) {
323 // no space for relocation information provided => code cannot be
324 // relocated. Make sure that relocate is only called with rtypes
325 // that can be ignored for this kind of code.
326 assert(rtype == relocInfo::none ||
327 rtype == relocInfo::runtime_call_type ||
328 rtype == relocInfo::internal_word_type||
329 rtype == relocInfo::section_word_type ||
330 rtype == relocInfo::external_word_type||
331 rtype == relocInfo::barrier_type,
332 "code needs relocation information");
333 // leave behind an indication that we attempted a relocation
334 DEBUG_ONLY(_locs_start = _locs_limit = (relocInfo*)badAddress);
335 return;
336 }
337
338 // Advance the point, noting the offset we'll have to record.
339 csize_t offset = at - locs_point();
340 set_locs_point(at);
341
342 // Test for a couple of overflow conditions; maybe expand the buffer.
343 relocInfo* end = locs_end();
344 relocInfo* req = end + relocInfo::length_limit;
345 // Check for (potential) overflow
346 if (req >= locs_limit() || offset >= relocInfo::offset_limit()) {
347 req += (uint)offset / (uint)relocInfo::offset_limit();
348 if (req >= locs_limit()) {
349 // Allocate or reallocate.
350 expand_locs(locs_count() + (req - end));
351 // reload pointer
352 end = locs_end();
353 }
354 }
355
356 // If the offset is giant, emit filler relocs, of type 'none', but
357 // each carrying the largest possible offset, to advance the locs_point.
358 while (offset >= relocInfo::offset_limit()) {
359 assert(end < locs_limit(), "adjust previous paragraph of code");
360 *end++ = relocInfo::filler_info();
361 offset -= relocInfo::filler_info().addr_offset();
362 }
363
364 // If it's a simple reloc with no data, we'll just write (rtype | offset).
365 (*end) = relocInfo(rtype, offset, format);
366
367 // If it has data, insert the prefix, as (data_prefix_tag | data1), data2.
368 end->initialize(this, reloc);
369 }
370
371 void CodeSection::initialize_locs(int locs_capacity) {
372 assert(_locs_start == nullptr, "only one locs init step, please");
373 // Apply a priori lower limits to relocation size:
374 csize_t min_locs = MAX2(size() / 16, (csize_t)4);
375 if (locs_capacity < min_locs) locs_capacity = min_locs;
376 relocInfo* locs_start = NEW_RESOURCE_ARRAY(relocInfo, locs_capacity);
377 _locs_start = locs_start;
378 _locs_end = locs_start;
379 _locs_limit = locs_start + locs_capacity;
380 _locs_own = true;
381 }
382
383 void CodeSection::initialize_shared_locs(relocInfo* buf, int length) {
384 assert(_locs_start == nullptr, "do this before locs are allocated");
385 // Internal invariant: locs buf must be fully aligned.
386 // See copy_relocations_to() below.
387 while ((uintptr_t)buf % HeapWordSize != 0 && length > 0) {
388 ++buf; --length;
389 }
390 if (length > 0) {
391 _locs_start = buf;
392 _locs_end = buf;
393 _locs_limit = buf + length;
394 _locs_own = false;
395 }
396 }
397
398 void CodeSection::initialize_locs_from(const CodeSection* source_cs) {
399 int lcount = source_cs->locs_count();
400 if (lcount != 0) {
401 initialize_shared_locs(source_cs->locs_start(), lcount);
402 _locs_end = _locs_limit = _locs_start + lcount;
403 assert(is_allocated(), "must have copied code already");
404 set_locs_point(start() + source_cs->locs_point_off());
405 }
406 assert(this->locs_count() == source_cs->locs_count(), "sanity");
407 }
408
409 void CodeSection::expand_locs(int new_capacity) {
410 if (_locs_start == nullptr) {
411 initialize_locs(new_capacity);
412 return;
413 } else {
414 int old_count = locs_count();
415 int old_capacity = locs_capacity();
416 if (new_capacity < old_capacity * 2)
417 new_capacity = old_capacity * 2;
418 relocInfo* locs_start;
419 if (_locs_own) {
420 locs_start = REALLOC_RESOURCE_ARRAY(_locs_start, old_capacity, new_capacity);
421 } else {
422 locs_start = NEW_RESOURCE_ARRAY(relocInfo, new_capacity);
423 Copy::conjoint_jbytes(_locs_start, locs_start, old_capacity * sizeof(relocInfo));
424 _locs_own = true;
425 }
426 _locs_start = locs_start;
427 _locs_end = locs_start + old_count;
428 _locs_limit = locs_start + new_capacity;
429 }
430 }
431
432 int CodeSection::alignment() const {
433 if (_index == CodeBuffer::SECT_CONSTS) {
434 // CodeBuffer controls the alignment of the constants section
435 return _outer->_const_section_alignment;
436 }
437 if (_index == CodeBuffer::SECT_INSTS) {
438 return (int) CodeEntryAlignment;
439 }
440 if (_index == CodeBuffer::SECT_STUBS) {
441 // CodeBuffer installer expects sections to be HeapWordSize aligned
442 return HeapWordSize;
443 }
444 ShouldNotReachHere();
445 return 0;
446 }
447
448 /// Support for emitting the code to its final location.
449 /// The pattern is the same for all functions.
450 /// We iterate over all the sections, padding each to alignment.
451
452 csize_t CodeBuffer::total_content_size() const {
453 csize_t size_so_far = 0;
454 for (int n = 0; n < (int)SECT_LIMIT; n++) {
455 const CodeSection* cs = code_section(n);
456 if (cs->is_empty()) continue; // skip trivial section
457 size_so_far = cs->align_at_start(size_so_far);
458 size_so_far += cs->size();
459 }
460 return size_so_far;
461 }
462
463 void CodeBuffer::compute_final_layout(CodeBuffer* dest) const {
464 address buf = dest->_total_start;
465 csize_t buf_offset = 0;
466 assert(dest->_total_size >= total_content_size(), "must be big enough");
467 assert(!_finalize_stubs, "non-finalized stubs");
468
469 {
470 assert( (dest->_total_start - _insts.start()) % CodeEntryAlignment == 0, "copy must preserve alignment");
471 }
472
473 const CodeSection* prev_cs = nullptr;
474 CodeSection* prev_dest_cs = nullptr;
475
476 for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) {
477 // figure compact layout of each section
478 const CodeSection* cs = code_section(n);
479 csize_t csize = cs->size();
480
481 CodeSection* dest_cs = dest->code_section(n);
482 if (!cs->is_empty()) {
483 // Compute initial padding; assign it to the previous non-empty guy.
484 // Cf. figure_expanded_capacities.
485 csize_t padding = cs->align_at_start(buf_offset) - buf_offset;
486 if (prev_dest_cs != nullptr) {
487 if (padding != 0) {
488 buf_offset += padding;
489 prev_dest_cs->_limit += padding;
490 }
491 } else {
492 guarantee(padding == 0, "In first iteration no padding should be needed.");
493 }
494 prev_dest_cs = dest_cs;
495 prev_cs = cs;
496 }
497
498 DEBUG_ONLY(dest_cs->_start = nullptr); // defeat double-initialization assert
499 dest_cs->initialize(buf+buf_offset, csize);
500 dest_cs->set_end(buf+buf_offset+csize);
501 assert(dest_cs->is_allocated(), "must always be allocated");
502 assert(cs->is_empty() == dest_cs->is_empty(), "sanity");
503
504 buf_offset += csize;
505 }
506
507 // Done calculating sections; did it come out to the right end?
508 assert(buf_offset == total_content_size(), "sanity");
509 DEBUG_ONLY(dest->verify_section_allocation();)
510 }
511
512 // Append an oop reference that keeps the class alive.
513 static void append_oop_references(GrowableArray<oop>* oops, Klass* k) {
514 oop cl = k->klass_holder();
515 if (cl != nullptr && !oops->contains(cl)) {
516 oops->append(cl);
517 }
518 }
519
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++) {
590 oop_recorder()->find_index((jobject)thread->handle_area()->allocate_handle(oops.at(i)));
591 }
592 }
593
594
595
596 csize_t CodeBuffer::total_offset_of(const CodeSection* cs) const {
597 csize_t size_so_far = 0;
598 for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) {
599 const CodeSection* cur_cs = code_section(n);
600 if (!cur_cs->is_empty()) {
601 size_so_far = cur_cs->align_at_start(size_so_far);
602 }
603 if (cur_cs->index() == cs->index()) {
604 return size_so_far;
605 }
606 size_so_far += cur_cs->size();
607 }
608 ShouldNotReachHere();
609 return -1;
610 }
611
612 int CodeBuffer::total_skipped_instructions_size() const {
613 int total_skipped_size = 0;
614 for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) {
615 const CodeSection* cur_cs = code_section(n);
616 if (!cur_cs->is_empty()) {
617 total_skipped_size += cur_cs->_skipped_instructions_size;
618 }
619 }
620 return total_skipped_size;
621 }
622
623 csize_t CodeBuffer::total_relocation_size() const {
624 csize_t total = copy_relocations_to(nullptr); // dry run only
625 return (csize_t) align_up(total, HeapWordSize);
626 }
627
628 csize_t CodeBuffer::copy_relocations_to(address buf, csize_t buf_limit) const {
629 csize_t buf_offset = 0;
630 csize_t code_end_so_far = 0;
631 csize_t code_point_so_far = 0;
632
633 assert((uintptr_t)buf % HeapWordSize == 0, "buf must be fully aligned");
634 assert(buf_limit % HeapWordSize == 0, "buf must be evenly sized");
635
636 for (int n = (int) SECT_FIRST; n < (int)SECT_LIMIT; n++) {
637 // pull relocs out of each section
638 const CodeSection* cs = code_section(n);
639 assert(!(cs->is_empty() && cs->locs_count() > 0), "sanity");
640 if (cs->is_empty()) continue; // skip trivial section
641 relocInfo* lstart = cs->locs_start();
642 relocInfo* lend = cs->locs_end();
643 csize_t lsize = (csize_t)( (address)lend - (address)lstart );
644 csize_t csize = cs->size();
645 code_end_so_far = cs->align_at_start(code_end_so_far);
646
647 if (lsize > 0) {
648 // Figure out how to advance the combined relocation point
649 // first to the beginning of this section.
650 // We'll insert one or more filler relocs to span that gap.
651 // (Don't bother to improve this by editing the first reloc's offset.)
652 csize_t new_code_point = code_end_so_far;
653 for (csize_t jump;
654 code_point_so_far < new_code_point;
655 code_point_so_far += jump) {
656 jump = new_code_point - code_point_so_far;
657 relocInfo filler = relocInfo::filler_info();
658 if (jump >= filler.addr_offset()) {
659 jump = filler.addr_offset();
660 } else { // else shrink the filler to fit
661 filler = relocInfo(relocInfo::none, jump);
662 }
663 if (buf != nullptr) {
664 assert(buf_offset + (csize_t)sizeof(filler) <= buf_limit, "filler in bounds");
665 *(relocInfo*)(buf+buf_offset) = filler;
666 }
667 buf_offset += sizeof(filler);
668 }
669
670 // Update code point and end to skip past this section:
671 csize_t last_code_point = code_end_so_far + cs->locs_point_off();
672 assert(code_point_so_far <= last_code_point, "sanity");
673 code_point_so_far = last_code_point; // advance past this guy's relocs
674 }
675 code_end_so_far += csize; // advance past this guy's instructions too
676
677 // Done with filler; emit the real relocations:
678 if (buf != nullptr && lsize != 0) {
679 assert(buf_offset + lsize <= buf_limit, "target in bounds");
680 assert((uintptr_t)lstart % HeapWordSize == 0, "sane start");
681 if (buf_offset % HeapWordSize == 0) {
682 // Use wordwise copies if possible:
683 Copy::disjoint_words((HeapWord*)lstart,
684 (HeapWord*)(buf+buf_offset),
685 (lsize + HeapWordSize-1) / HeapWordSize);
686 } else {
687 Copy::conjoint_jbytes(lstart, buf+buf_offset, lsize);
688 }
689 }
690 buf_offset += lsize;
691 }
692
693 // Align end of relocation info in target.
694 while (buf_offset % HeapWordSize != 0) {
695 if (buf != nullptr) {
696 relocInfo padding = relocInfo(relocInfo::none, 0);
697 assert(buf_offset + (csize_t)sizeof(padding) <= buf_limit, "padding in bounds");
698 *(relocInfo*)(buf+buf_offset) = padding;
699 }
700 buf_offset += sizeof(relocInfo);
701 }
702
703 assert(code_end_so_far == total_content_size(), "sanity");
704
705 return buf_offset;
706 }
707
708 csize_t CodeBuffer::copy_relocations_to(CodeBlob* dest) const {
709 address buf = nullptr;
710 csize_t buf_offset = 0;
711 csize_t buf_limit = 0;
712
713 if (dest != nullptr) {
714 buf = (address)dest->relocation_begin();
715 buf_limit = (address)dest->relocation_end() - buf;
716 }
717 // if dest is null, this is just the sizing pass
718 //
719 buf_offset = copy_relocations_to(buf, buf_limit);
720
721 return buf_offset;
722 }
723
724 void CodeBuffer::copy_code_to(CodeBlob* dest_blob) {
725 #ifndef PRODUCT
726 if (PrintNMethods && (WizardMode || Verbose)) {
727 tty->print("done with CodeBuffer:");
728 ((CodeBuffer*)this)->print_on(tty);
729 }
730 #endif //PRODUCT
731
732 CodeBuffer dest(dest_blob);
733 assert(dest_blob->content_size() >= total_content_size(), "good sizing");
734 this->compute_final_layout(&dest);
735
736 // Set beginning of constant table before relocating.
737 dest_blob->set_ctable_begin(dest.consts()->start());
738
739 relocate_code_to(&dest);
740
741 // Share assembly remarks and debug strings with the blob.
742 NOT_PRODUCT(dest_blob->use_remarks(_asm_remarks));
743 NOT_PRODUCT(dest_blob->use_strings(_dbg_strings));
744
745 // Done moving code bytes; were they the right size?
746 assert((int)align_up(dest.total_content_size(), oopSize) == dest_blob->content_size(), "sanity");
747 }
748
749 // Move all my code into another code buffer. Consult applicable
750 // relocs to repair embedded addresses. The layout in the destination
751 // CodeBuffer is different to the source CodeBuffer: the destination
752 // CodeBuffer gets the final layout (consts, insts, stubs in order of
753 // ascending address).
754 void CodeBuffer::relocate_code_to(CodeBuffer* dest) const {
755 address dest_end = dest->_total_start + dest->_total_size;
756 address dest_filled = nullptr;
757 for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) {
758 // pull code out of each section
759 const CodeSection* cs = code_section(n);
760 if (cs->is_empty()) continue; // skip trivial section
761 CodeSection* dest_cs = dest->code_section(n);
762 assert(cs->size() == dest_cs->size(), "sanity");
763 csize_t usize = dest_cs->size();
764 csize_t wsize = align_up(usize, HeapWordSize);
765 assert(dest_cs->start() + wsize <= dest_end, "no overflow");
766 // Copy the code as aligned machine words.
767 // This may also include an uninitialized partial word at the end.
768 Copy::disjoint_words((HeapWord*)cs->start(),
769 (HeapWord*)dest_cs->start(),
770 wsize / HeapWordSize);
771
772 if (dest->blob() == nullptr) {
773 // Destination is a final resting place, not just another buffer.
774 // Normalize uninitialized bytes in the final padding.
775 Copy::fill_to_bytes(dest_cs->end(), dest_cs->remaining(),
776 Assembler::code_fill_byte());
777 }
778 // Keep track of the highest filled address
779 dest_filled = MAX2(dest_filled, dest_cs->end() + dest_cs->remaining());
780
781 assert(cs->locs_start() != (relocInfo*)badAddress,
782 "this section carries no reloc storage, but reloc was attempted");
783
784 // Make the new code copy use the old copy's relocations:
785 dest_cs->initialize_locs_from(cs);
786 }
787
788 // Do relocation after all sections are copied.
789 // This is necessary if the code uses constants in stubs, which are
790 // relocated when the corresponding instruction in the code (e.g., a
791 // call) is relocated. Stubs are placed behind the main code
792 // section, so that section has to be copied before relocating.
793 for (int n = (int) SECT_FIRST; n < (int)SECT_LIMIT; n++) {
794 CodeSection* dest_cs = dest->code_section(n);
795 if (dest_cs->is_empty() || (dest_cs->locs_count() == 0)) continue; // skip trivial section
796 { // Repair the pc relative information in the code after the move
797 RelocIterator iter(dest_cs);
798 while (iter.next()) {
799 iter.reloc()->fix_relocation_after_move(this, dest);
800 }
801 }
802 }
803
804 if (dest->blob() == nullptr && dest_filled != nullptr) {
805 // Destination is a final resting place, not just another buffer.
806 // Normalize uninitialized bytes in the final padding.
807 Copy::fill_to_bytes(dest_filled, dest_end - dest_filled,
808 Assembler::code_fill_byte());
809
810 }
811 }
812
813 csize_t CodeBuffer::figure_expanded_capacities(CodeSection* which_cs,
814 csize_t amount,
815 csize_t* new_capacity) {
816 csize_t new_total_cap = 0;
817
818 for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) {
819 const CodeSection* sect = code_section(n);
820
821 if (!sect->is_empty()) {
822 // Compute initial padding; assign it to the previous section,
823 // even if it's empty (e.g. consts section can be empty).
824 // Cf. compute_final_layout
825 csize_t padding = sect->align_at_start(new_total_cap) - new_total_cap;
826 if (padding != 0) {
827 new_total_cap += padding;
828 assert(n - 1 >= SECT_FIRST, "sanity");
829 new_capacity[n - 1] += padding;
830 }
831 }
832
833 csize_t exp = sect->size(); // 100% increase
834 if ((uint)exp < 4*K) exp = 4*K; // minimum initial increase
835 if (sect == which_cs) {
836 if (exp < amount) exp = amount;
837 if (StressCodeBuffers) exp = amount; // expand only slightly
838 } else if (n == SECT_INSTS) {
839 // scale down inst increases to a more modest 25%
840 exp = 4*K + ((exp - 4*K) >> 2);
841 if (StressCodeBuffers) exp = amount / 2; // expand only slightly
842 } else if (sect->is_empty()) {
843 // do not grow an empty secondary section
844 exp = 0;
845 }
846 // Allow for inter-section slop:
847 exp += CodeSection::end_slop();
848 csize_t new_cap = sect->size() + exp;
849 if (new_cap < sect->capacity()) {
850 // No need to expand after all.
851 new_cap = sect->capacity();
852 }
853 new_capacity[n] = new_cap;
854 new_total_cap += new_cap;
855 }
856
857 return new_total_cap;
858 }
859
860 void CodeBuffer::expand(CodeSection* which_cs, csize_t amount) {
861 #ifdef ASSERT
862 // The code below copies contents across temp buffers. The following
863 // sizes relate to buffer contents, and should not be changed by buffer
864 // expansion.
865 int old_total_skipped = total_skipped_instructions_size();
866 #endif
867
868 #ifndef PRODUCT
869 if (PrintNMethods && (WizardMode || Verbose)) {
870 tty->print("expanding CodeBuffer:");
871 this->print_on(tty);
872 }
873
874 if (StressCodeBuffers && blob() != nullptr) {
875 static int expand_count = 0;
876 if (expand_count >= 0) expand_count += 1;
877 if (expand_count > 100 && is_power_of_2(expand_count)) {
878 tty->print_cr("StressCodeBuffers: have expanded %d times", expand_count);
879 // simulate an occasional allocation failure:
880 free_blob();
881 }
882 }
883 #endif //PRODUCT
884
885 // Resizing must be allowed
886 {
887 if (blob() == nullptr) return; // caller must check if blob is null
888 }
889
890 // Figure new capacity for each section.
891 csize_t new_capacity[SECT_LIMIT];
892 memset(new_capacity, 0, sizeof(csize_t) * SECT_LIMIT);
893 csize_t new_total_cap
894 = figure_expanded_capacities(which_cs, amount, new_capacity);
895
896 // Create a new (temporary) code buffer to hold all the new data
897 CodeBuffer cb(name(), new_total_cap, 0);
898 cb.set_const_section_alignment(_const_section_alignment);
899 if (cb.blob() == nullptr) {
900 // Failed to allocate in code cache.
901 free_blob();
902 return;
903 }
904
905 // Create an old code buffer to remember which addresses used to go where.
906 // This will be useful when we do final assembly into the code cache,
907 // because we will need to know how to warp any internal address that
908 // has been created at any time in this CodeBuffer's past.
909 CodeBuffer* bxp = new CodeBuffer(_total_start, _total_size);
910 bxp->take_over_code_from(this); // remember the old undersized blob
911 DEBUG_ONLY(this->_blob = nullptr); // silence a later assert
912 bxp->_before_expand = this->_before_expand;
913 this->_before_expand = bxp;
914
915 // Give each section its required (expanded) capacity.
916 for (int n = (int)SECT_LIMIT-1; n >= SECT_FIRST; n--) {
917 CodeSection* cb_sect = cb.code_section(n);
918 CodeSection* this_sect = code_section(n);
919 if (new_capacity[n] == 0) continue; // already nulled out
920 if (n != SECT_INSTS) {
921 cb.initialize_section_size(cb_sect, new_capacity[n]);
922 }
923 assert(cb_sect->capacity() >= new_capacity[n], "big enough");
924 address cb_start = cb_sect->start();
925 cb_sect->set_end(cb_start + this_sect->size());
926 cb_sect->register_skipped(this_sect->_skipped_instructions_size);
927 if (this_sect->mark() == nullptr) {
928 cb_sect->clear_mark();
929 } else {
930 cb_sect->set_mark(cb_start + this_sect->mark_off());
931 }
932 }
933
934 // Needs to be initialized when calling fix_relocation_after_move.
935 cb.blob()->set_ctable_begin(cb.consts()->start());
936
937 // Move all the code and relocations to the new blob:
938 relocate_code_to(&cb);
939
940 // some internal addresses, _last_merge_candidate and _last_label, are used during
941 // code emission, adjust them in expansion
942 adjust_internal_address(insts_begin(), cb.insts_begin());
943
944 // Copy the temporary code buffer into the current code buffer.
945 // Basically, do {*this = cb}, except for some control information.
946 this->take_over_code_from(&cb);
947 cb.set_blob(nullptr);
948
949 // Zap the old code buffer contents, to avoid mistakenly using them.
950 DEBUG_ONLY(Copy::fill_to_bytes(bxp->_total_start, bxp->_total_size,
951 badCodeHeapFreeVal);)
952
953 // Make certain that the new sections are all snugly inside the new blob.
954 DEBUG_ONLY(verify_section_allocation();)
955
956 #ifndef PRODUCT
957 _decode_begin = nullptr; // sanity
958 if (PrintNMethods && (WizardMode || Verbose)) {
959 tty->print("expanded CodeBuffer:");
960 this->print_on(tty);
961 }
962 #endif //PRODUCT
963
964 assert(old_total_skipped == total_skipped_instructions_size(),
965 "Should match: %d == %d", old_total_skipped, total_skipped_instructions_size());
966 }
967
968 void CodeBuffer::adjust_internal_address(address from, address to) {
969 if (_last_merge_candidate != nullptr) {
970 _last_merge_candidate += to - from;
971 }
972 if (_last_label != nullptr) {
973 _last_label += to - from;
974 }
975 }
976
977 void CodeBuffer::take_over_code_from(CodeBuffer* cb) {
978 // Must already have disposed of the old blob somehow.
979 assert(blob() == nullptr, "must be empty");
980 // Take the new blob away from cb.
981 set_blob(cb->blob());
982 // Take over all the section pointers.
983 for (int n = 0; n < (int)SECT_LIMIT; n++) {
984 CodeSection* cb_sect = cb->code_section(n);
985 CodeSection* this_sect = code_section(n);
986 this_sect->take_over_code_from(cb_sect);
987 }
988 // Make sure the old cb won't try to use it or free it.
989 DEBUG_ONLY(cb->_blob = (BufferBlob*)badAddress);
990 }
991
992 void CodeBuffer::verify_section_allocation() {
993 address tstart = _total_start;
994 if (tstart == nullptr) return; // ignore not fully initialized buffer
995 if (tstart == badAddress) return; // smashed by set_blob(nullptr)
996 address tend = tstart + _total_size;
997 if (_blob != nullptr) {
998 guarantee(tstart >= _blob->content_begin(), "sanity");
999 guarantee(tend <= _blob->content_end(), "sanity");
1000 }
1001 // Verify disjointness.
1002 for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) {
1003 CodeSection* sect = code_section(n);
1004 if (!sect->is_allocated() || sect->is_empty()) {
1005 continue;
1006 }
1007 guarantee(_blob == nullptr || is_aligned(sect->start(), sect->alignment()),
1008 "start is aligned");
1009 for (int m = n + 1; m < (int) SECT_LIMIT; m++) {
1010 CodeSection* other = code_section(m);
1011 if (!other->is_allocated() || other == sect) {
1012 continue;
1013 }
1014 guarantee(other->disjoint(sect), "sanity");
1015 }
1016 guarantee(sect->end() <= tend, "sanity");
1017 guarantee(sect->end() <= sect->limit(), "sanity");
1018 }
1019 }
1020
1021 void CodeBuffer::log_section_sizes(const char* name) {
1022 if (xtty != nullptr) {
1023 ttyLocker ttyl;
1024 // log info about buffer usage
1025 xtty->print_cr("<blob name='%s' total_size='%d'>", name, _total_size);
1026 for (int n = (int) CodeBuffer::SECT_FIRST; n < (int) CodeBuffer::SECT_LIMIT; n++) {
1027 CodeSection* sect = code_section(n);
1028 if (!sect->is_allocated() || sect->is_empty()) continue;
1029 xtty->print_cr("<sect index='%d' capacity='%d' size='%d' remaining='%d'/>",
1030 n, sect->capacity(), sect->size(), sect->remaining());
1031 }
1032 xtty->print_cr("</blob>");
1033 }
1034 }
1035
1036 bool CodeBuffer::finalize_stubs() {
1037 if (_finalize_stubs && !pd_finalize_stubs()) {
1038 // stub allocation failure
1039 return false;
1040 }
1041 _finalize_stubs = false;
1042 return true;
1043 }
1044
1045 void CodeBuffer::shared_stub_to_interp_for(ciMethod* callee, csize_t call_offset) {
1046 if (_shared_stub_to_interp_requests == nullptr) {
1047 _shared_stub_to_interp_requests = new SharedStubToInterpRequests(8);
1048 }
1049 SharedStubToInterpRequest request(callee, call_offset);
1050 _shared_stub_to_interp_requests->push(request);
1051 _finalize_stubs = true;
1052 }
1053
1054 #ifndef PRODUCT
1055 void CodeBuffer::block_comment(ptrdiff_t offset, const char* comment) {
1056 if (insts()->scratch_emit()) {
1057 return;
1058 }
1059 if (_collect_comments) {
1060 const char* str = _asm_remarks.insert(offset, comment);
1061 postcond(str != comment);
1062 }
1063 }
1064
1065 const char* CodeBuffer::code_string(const char* str) {
1066 if (insts()->scratch_emit()) {
1067 return str;
1068 }
1069 const char* tmp = _dbg_strings.insert(str);
1070 postcond(tmp != str);
1071 return tmp;
1072 }
1073
1074 void CodeBuffer::decode() {
1075 ttyLocker ttyl;
1076 Disassembler::decode(decode_begin(), insts_end(), tty NOT_PRODUCT(COMMA &asm_remarks()));
1077 _decode_begin = insts_end();
1078 }
1079
1080 void CodeSection::print_on(outputStream* st, const char* name) {
1081 csize_t locs_size = locs_end() - locs_start();
1082 st->print_cr(" %7s.code = " PTR_FORMAT " : " PTR_FORMAT " : " PTR_FORMAT " (%d of %d)",
1083 name, p2i(start()), p2i(end()), p2i(limit()), size(), capacity());
1084 st->print_cr(" %7s.locs = " PTR_FORMAT " : " PTR_FORMAT " : " PTR_FORMAT " (%d of %d) point=%d",
1085 name, p2i(locs_start()), p2i(locs_end()), p2i(locs_limit()), locs_size, locs_capacity(), locs_point_off());
1086 if (PrintRelocations && (locs_size != 0)) {
1087 RelocIterator iter(this);
1088 iter.print_on(st);
1089 }
1090 }
1091
1092 void CodeBuffer::print_on(outputStream* st) {
1093 st->print_cr("CodeBuffer:%s", name());
1094 for (int n = 0; n < (int)SECT_LIMIT; n++) {
1095 // print each section
1096 CodeSection* cs = code_section(n);
1097 cs->print_on(st, code_section_name(n));
1098 }
1099 }
1100
1101 CHeapString::~CHeapString() {
1102 os::free((void*)_string);
1103 _string = nullptr;
1104 }
1105
1106 // ----- AsmRemarks ------------------------------------------------------------
1107 //
1108 // Acting as interface to reference counted mapping [offset -> remark], where
1109 // offset is a byte offset into an instruction stream (CodeBuffer, CodeBlob or
1110 // other memory buffer) and remark is a string (comment).
1111 //
1112 AsmRemarks::AsmRemarks() {
1113 init();
1114 assert(_remarks != nullptr, "Allocation failure!");
1115 }
1116
1117 AsmRemarks::~AsmRemarks() {
1118 assert(_remarks == nullptr, "Must 'clear()' before deleting!");
1119 }
1120
1121 void AsmRemarks::init() {
1122 _remarks = new AsmRemarkCollection();
1123 }
1124
1125 const char* AsmRemarks::insert(uint offset, const char* remstr) {
1126 precond(remstr != nullptr);
1127 return _remarks->insert(offset, remstr);
1128 }
1129
1130 bool AsmRemarks::is_empty() const {
1131 return _remarks->is_empty();
1132 }
1133
1134 void AsmRemarks::share(const AsmRemarks &src) {
1135 precond(_remarks == nullptr || is_empty());
1136 clear();
1137 _remarks = src._remarks->reuse();
1138 }
1139
1140 void AsmRemarks::clear() {
1141 if (_remarks != nullptr && _remarks->clear() == 0) {
1142 delete _remarks;
1143 }
1144 _remarks = nullptr;
1145 }
1146
1147 uint AsmRemarks::print(uint offset, outputStream* strm) const {
1148 uint count = 0;
1149 const char* prefix = " ;; ";
1150 const char* remstr = (_remarks ? _remarks->lookup(offset) : nullptr);
1151 while (remstr != nullptr) {
1152 strm->bol();
1153 strm->print("%s", prefix);
1154 // Don't interpret as format strings since it could contain '%'.
1155 strm->print_raw(remstr);
1156 // Advance to next line iff string didn't contain a cr() at the end.
1157 strm->bol();
1158 remstr = _remarks->next(offset);
1159 count++;
1160 }
1161 return count;
1162 }
1163
1164 // ----- DbgStrings ------------------------------------------------------------
1165 //
1166 // Acting as interface to reference counted collection of (debug) strings used
1167 // in the code generated, and thus requiring a fixed address.
1168 //
1169 DbgStrings::DbgStrings() {
1170 init();
1171 assert(_strings != nullptr, "Allocation failure!");
1172 }
1173
1174 DbgStrings::~DbgStrings() {
1175 assert(_strings == nullptr, "Must 'clear()' before deleting!");
1176 }
1177
1178 void DbgStrings::init() {
1179 _strings = new DbgStringCollection();
1180 }
1181
1182 const char* DbgStrings::insert(const char* dbgstr) {
1183 const char* str = _strings->lookup(dbgstr);
1184 return str != nullptr ? str : _strings->insert(dbgstr);
1185 }
1186
1187 bool DbgStrings::is_empty() const {
1188 return _strings->is_empty();
1189 }
1190
1191 void DbgStrings::share(const DbgStrings &src) {
1192 precond(_strings == nullptr || is_empty());
1193 clear();
1194 _strings = src._strings->reuse();
1195 }
1196
1197 void DbgStrings::clear() {
1198 if (_strings != nullptr && _strings->clear() == 0) {
1199 delete _strings;
1200 }
1201 _strings = nullptr;
1202 }
1203
1204 // ----- AsmRemarkCollection ---------------------------------------------------
1205
1206 const char* AsmRemarkCollection::insert(uint offset, const char* remstr) {
1207 precond(remstr != nullptr);
1208 Cell* cell = new Cell { remstr, offset };
1209 if (is_empty()) {
1210 cell->prev = cell;
1211 cell->next = cell;
1212 _remarks = cell;
1213 } else {
1214 _remarks->push_back(cell);
1215 }
1216 return cell->string();
1217 }
1218
1219 const char* AsmRemarkCollection::lookup(uint offset) const {
1220 _next = _remarks;
1221 return next(offset);
1222 }
1223
1224 const char* AsmRemarkCollection::next(uint offset) const {
1225 if (_next != nullptr) {
1226 Cell* i = _next;
1227 do {
1228 if (i->offset == offset) {
1229 _next = i->next == _remarks ? nullptr : i->next;
1230 return i->string();
1231 }
1232 i = i->next;
1233 } while (i != _remarks);
1234 _next = nullptr;
1235 }
1236 return nullptr;
1237 }
1238
1239 uint AsmRemarkCollection::clear() {
1240 precond(_ref_cnt > 0);
1241 if (--_ref_cnt > 0) {
1242 return _ref_cnt;
1243 }
1244 if (!is_empty()) {
1245 uint count = 0;
1246 Cell* i = _remarks;
1247 do {
1248 Cell* next = i->next;
1249 delete i;
1250 i = next;
1251 count++;
1252 } while (i != _remarks);
1253
1254 log_debug(codestrings)("Clear %u asm-remark%s.", count, count == 1 ? "" : "s");
1255 _remarks = nullptr;
1256 }
1257 return 0; // i.e. _ref_cnt == 0
1258 }
1259
1260 // ----- DbgStringCollection ---------------------------------------------------
1261
1262 const char* DbgStringCollection::insert(const char* dbgstr) {
1263 precond(dbgstr != nullptr);
1264 Cell* cell = new Cell { dbgstr };
1265
1266 if (is_empty()) {
1267 cell->prev = cell;
1268 cell->next = cell;
1269 _strings = cell;
1270 } else {
1271 _strings->push_back(cell);
1272 }
1273 return cell->string();
1274 }
1275
1276 const char* DbgStringCollection::lookup(const char* dbgstr) const {
1277 precond(dbgstr != nullptr);
1278 if (_strings != nullptr) {
1279 Cell* i = _strings;
1280 do {
1281 if (strcmp(i->string(), dbgstr) == 0) {
1282 return i->string();
1283 }
1284 i = i->next;
1285 } while (i != _strings);
1286 }
1287 return nullptr;
1288 }
1289
1290 uint DbgStringCollection::clear() {
1291 precond(_ref_cnt > 0);
1292 if (--_ref_cnt > 0) {
1293 return _ref_cnt;
1294 }
1295 if (!is_empty()) {
1296 uint count = 0;
1297 Cell* i = _strings;
1298 do {
1299 Cell* next = i->next;
1300 delete i;
1301 i = next;
1302 count++;
1303 } while (i != _strings);
1304
1305 log_debug(codestrings)("Clear %u dbg-string%s.", count, count == 1 ? "" : "s");
1306 _strings = nullptr;
1307 }
1308 return 0; // i.e. _ref_cnt == 0
1309 }
1310
1311 #endif // not PRODUCT