Mercurial > hg > truffle
annotate src/share/vm/asm/codeBuffer.cpp @ 20543:e7d0505c8a30
8059758: Footprint regressions with JDK-8038423
Summary: Changes in JDK-8038423 always initialize (zero out) virtual memory used for auxiliary data structures. This causes a footprint regression for G1 in startup benchmarks. This is because they do not touch that memory at all, so the operating system does not actually commit these pages. The fix is to, if the initialization value of the data structures matches the default value of just committed memory (=0), do not do anything.
Reviewed-by: jwilhelm, brutisso
author | tschatzl |
---|---|
date | Fri, 10 Oct 2014 15:51:58 +0200 |
parents | 094cbdffa87d |
children | 7848fc12602b |
rev | line source |
---|---|
0 | 1 /* |
17937
78bbf4d43a14
8037816: Fix for 8036122 breaks build with Xcode5/clang
drchase
parents:
17467
diff
changeset
|
2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
579
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
579
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
579
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "asm/codeBuffer.hpp" | |
27 #include "compiler/disassembler.hpp" | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
28 #include "memory/gcLocker.hpp" |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
29 #include "oops/methodData.hpp" |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
30 #include "oops/oop.inline.hpp" |
1972 | 31 #include "utilities/copy.hpp" |
4059
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
32 #include "utilities/xmlstream.hpp" |
0 | 33 |
34 // The structure of a CodeSection: | |
35 // | |
36 // _start -> +----------------+ | |
37 // | machine code...| | |
38 // _end -> |----------------| | |
39 // | | | |
40 // | (empty) | | |
41 // | | | |
42 // | | | |
43 // +----------------+ | |
44 // _limit -> | | | |
45 // | |
46 // _locs_start -> +----------------+ | |
47 // |reloc records...| | |
48 // |----------------| | |
49 // _locs_end -> | | | |
50 // | | | |
51 // | (empty) | | |
52 // | | | |
53 // | | | |
54 // +----------------+ | |
55 // _locs_limit -> | | | |
56 // The _end (resp. _limit) pointer refers to the first | |
57 // unused (resp. unallocated) byte. | |
58 | |
59 // The structure of the CodeBuffer while code is being accumulated: | |
60 // | |
61 // _total_start -> \ | |
62 // _insts._start -> +----------------+ | |
63 // | | | |
64 // | Code | | |
65 // | | | |
66 // _stubs._start -> |----------------| | |
67 // | | | |
68 // | Stubs | (also handlers for deopt/exception) | |
69 // | | | |
70 // _consts._start -> |----------------| | |
71 // | | | |
72 // | Constants | | |
73 // | | | |
74 // +----------------+ | |
75 // + _total_size -> | | | |
76 // | |
77 // When the code and relocations are copied to the code cache, | |
78 // the empty parts of each section are removed, and everything | |
79 // is copied into contiguous locations. | |
80 | |
81 typedef CodeBuffer::csize_t csize_t; // file-local definition | |
82 | |
1748 | 83 // External buffer, in a predefined CodeBlob. |
0 | 84 // Important: The code_start must be taken exactly, and not realigned. |
1748 | 85 CodeBuffer::CodeBuffer(CodeBlob* blob) { |
0 | 86 initialize_misc("static buffer"); |
1748 | 87 initialize(blob->content_begin(), blob->content_size()); |
4059
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
88 verify_section_allocation(); |
0 | 89 } |
90 | |
91 void CodeBuffer::initialize(csize_t code_size, csize_t locs_size) { | |
92 // Compute maximal alignment. | |
93 int align = _insts.alignment(); | |
94 // Always allow for empty slop around each section. | |
95 int slop = (int) CodeSection::end_slop(); | |
96 | |
97 assert(blob() == NULL, "only once"); | |
98 set_blob(BufferBlob::create(_name, code_size + (align+slop) * (SECT_LIMIT+1))); | |
99 if (blob() == NULL) { | |
100 // The assembler constructor will throw a fatal on an empty CodeBuffer. | |
101 return; // caller must test this | |
102 } | |
103 | |
104 // Set up various pointers into the blob. | |
105 initialize(_total_start, _total_size); | |
106 | |
1748 | 107 assert((uintptr_t)insts_begin() % CodeEntryAlignment == 0, "instruction start not code entry aligned"); |
0 | 108 |
109 pd_initialize(); | |
110 | |
111 if (locs_size != 0) { | |
112 _insts.initialize_locs(locs_size / sizeof(relocInfo)); | |
113 } | |
114 | |
4059
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
115 verify_section_allocation(); |
0 | 116 } |
117 | |
118 | |
119 CodeBuffer::~CodeBuffer() { | |
4059
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
120 verify_section_allocation(); |
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
121 |
0 | 122 // If we allocate our code buffer from the CodeCache |
123 // via a BufferBlob, and it's not permanent, then | |
124 // free the BufferBlob. | |
125 // The rest of the memory will be freed when the ResourceObj | |
126 // is released. | |
127 for (CodeBuffer* cb = this; cb != NULL; cb = cb->before_expand()) { | |
128 // Previous incarnations of this buffer are held live, so that internal | |
129 // addresses constructed before expansions will not be confused. | |
130 cb->free_blob(); | |
131 } | |
561
5bfdb08ea692
6782260: Memory leak in CodeBuffer::create_patch_overflow
never
parents:
196
diff
changeset
|
132 |
5bfdb08ea692
6782260: Memory leak in CodeBuffer::create_patch_overflow
never
parents:
196
diff
changeset
|
133 // free any overflow storage |
5bfdb08ea692
6782260: Memory leak in CodeBuffer::create_patch_overflow
never
parents:
196
diff
changeset
|
134 delete _overflow_arena; |
5bfdb08ea692
6782260: Memory leak in CodeBuffer::create_patch_overflow
never
parents:
196
diff
changeset
|
135 |
20435 | 136 // Claim is that stack allocation ensures resources are cleaned up. |
137 // This is resource clean up, let's hope that all were properly copied out. | |
138 free_strings(); | |
139 | |
0 | 140 #ifdef ASSERT |
1685 | 141 // Save allocation type to execute assert in ~ResourceObj() |
142 // which is called after this destructor. | |
2015
79d8657be916
6993125: runThese crashes with assert(Thread::current()->on_local_stack((address)this))
kvn
parents:
1972
diff
changeset
|
143 assert(_default_oop_recorder.allocated_on_stack(), "should be embedded object"); |
1685 | 144 ResourceObj::allocation_type at = _default_oop_recorder.get_allocation_type(); |
0 | 145 Copy::fill_to_bytes(this, sizeof(*this), badResourceValue); |
1685 | 146 ResourceObj::set_allocation_type((address)(&_default_oop_recorder), at); |
0 | 147 #endif |
148 } | |
149 | |
150 void CodeBuffer::initialize_oop_recorder(OopRecorder* r) { | |
151 assert(_oop_recorder == &_default_oop_recorder && _default_oop_recorder.is_unused(), "do this once"); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
152 DEBUG_ONLY(_default_oop_recorder.freeze()); // force unused OR to be frozen |
0 | 153 _oop_recorder = r; |
154 } | |
155 | |
156 void CodeBuffer::initialize_section_size(CodeSection* cs, csize_t size) { | |
157 assert(cs != &_insts, "insts is the memory provider, not the consumer"); | |
158 csize_t slop = CodeSection::end_slop(); // margin between sections | |
159 int align = cs->alignment(); | |
160 assert(is_power_of_2(align), "sanity"); | |
161 address start = _insts._start; | |
162 address limit = _insts._limit; | |
163 address middle = limit - size; | |
164 middle -= (intptr_t)middle & (align-1); // align the division point downward | |
165 guarantee(middle - slop > start, "need enough space to divide up"); | |
166 _insts._limit = middle - slop; // subtract desired space, plus slop | |
167 cs->initialize(middle, limit - middle); | |
168 assert(cs->start() == middle, "sanity"); | |
169 assert(cs->limit() == limit, "sanity"); | |
170 // give it some relocations to start with, if the main section has them | |
171 if (_insts.has_locs()) cs->initialize_locs(1); | |
172 } | |
173 | |
174 void CodeBuffer::freeze_section(CodeSection* cs) { | |
175 CodeSection* next_cs = (cs == consts())? NULL: code_section(cs->index()+1); | |
176 csize_t frozen_size = cs->size(); | |
177 if (next_cs != NULL) { | |
178 frozen_size = next_cs->align_at_start(frozen_size); | |
179 } | |
180 address old_limit = cs->limit(); | |
181 address new_limit = cs->start() + frozen_size; | |
182 relocInfo* old_locs_limit = cs->locs_limit(); | |
183 relocInfo* new_locs_limit = cs->locs_end(); | |
184 // Patch the limits. | |
185 cs->_limit = new_limit; | |
186 cs->_locs_limit = new_locs_limit; | |
187 cs->_frozen = true; | |
188 if (!next_cs->is_allocated() && !next_cs->is_frozen()) { | |
189 // Give remaining buffer space to the following section. | |
190 next_cs->initialize(new_limit, old_limit - new_limit); | |
191 next_cs->initialize_shared_locs(new_locs_limit, | |
192 old_locs_limit - new_locs_limit); | |
193 } | |
194 } | |
195 | |
196 void CodeBuffer::set_blob(BufferBlob* blob) { | |
197 _blob = blob; | |
198 if (blob != NULL) { | |
1748 | 199 address start = blob->content_begin(); |
200 address end = blob->content_end(); | |
0 | 201 // Round up the starting address. |
202 int align = _insts.alignment(); | |
203 start += (-(intptr_t)start) & (align-1); | |
204 _total_start = start; | |
205 _total_size = end - start; | |
206 } else { | |
1762
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
207 #ifdef ASSERT |
0 | 208 // Clean out dangling pointers. |
209 _total_start = badAddress; | |
1762
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
210 _consts._start = _consts._end = badAddress; |
0 | 211 _insts._start = _insts._end = badAddress; |
212 _stubs._start = _stubs._end = badAddress; | |
1762
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
213 #endif //ASSERT |
0 | 214 } |
215 } | |
216 | |
217 void CodeBuffer::free_blob() { | |
218 if (_blob != NULL) { | |
219 BufferBlob::free(_blob); | |
220 set_blob(NULL); | |
221 } | |
222 } | |
223 | |
224 const char* CodeBuffer::code_section_name(int n) { | |
225 #ifdef PRODUCT | |
226 return NULL; | |
227 #else //PRODUCT | |
228 switch (n) { | |
1762
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
229 case SECT_CONSTS: return "consts"; |
0 | 230 case SECT_INSTS: return "insts"; |
231 case SECT_STUBS: return "stubs"; | |
232 default: return NULL; | |
233 } | |
234 #endif //PRODUCT | |
235 } | |
236 | |
237 int CodeBuffer::section_index_of(address addr) const { | |
238 for (int n = 0; n < (int)SECT_LIMIT; n++) { | |
239 const CodeSection* cs = code_section(n); | |
240 if (cs->allocates(addr)) return n; | |
241 } | |
242 return SECT_NONE; | |
243 } | |
244 | |
245 int CodeBuffer::locator(address addr) const { | |
246 for (int n = 0; n < (int)SECT_LIMIT; n++) { | |
247 const CodeSection* cs = code_section(n); | |
248 if (cs->allocates(addr)) { | |
249 return locator(addr - cs->start(), n); | |
250 } | |
251 } | |
252 return -1; | |
253 } | |
254 | |
255 address CodeBuffer::locator_address(int locator) const { | |
256 if (locator < 0) return NULL; | |
257 address start = code_section(locator_sect(locator))->start(); | |
258 return start + locator_pos(locator); | |
259 } | |
260 | |
7199
cd3d6a6b95d9
8003240: x86: move MacroAssembler into separate file
twisti
parents:
7197
diff
changeset
|
261 bool CodeBuffer::is_backward_branch(Label& L) { |
cd3d6a6b95d9
8003240: x86: move MacroAssembler into separate file
twisti
parents:
7197
diff
changeset
|
262 return L.is_bound() && insts_end() <= locator_address(L.loc()); |
cd3d6a6b95d9
8003240: x86: move MacroAssembler into separate file
twisti
parents:
7197
diff
changeset
|
263 } |
cd3d6a6b95d9
8003240: x86: move MacroAssembler into separate file
twisti
parents:
7197
diff
changeset
|
264 |
0 | 265 address CodeBuffer::decode_begin() { |
266 address begin = _insts.start(); | |
267 if (_decode_begin != NULL && _decode_begin > begin) | |
268 begin = _decode_begin; | |
269 return begin; | |
270 } | |
271 | |
272 | |
273 GrowableArray<int>* CodeBuffer::create_patch_overflow() { | |
274 if (_overflow_arena == NULL) { | |
20360 | 275 _overflow_arena = new (mtCode) Arena(mtCode); |
0 | 276 } |
277 return new (_overflow_arena) GrowableArray<int>(_overflow_arena, 8, 0, 0); | |
278 } | |
279 | |
280 | |
281 // Helper function for managing labels and their target addresses. | |
282 // Returns a sensible address, and if it is not the label's final | |
283 // address, notes the dependency (at 'branch_pc') on the label. | |
284 address CodeSection::target(Label& L, address branch_pc) { | |
285 if (L.is_bound()) { | |
286 int loc = L.loc(); | |
287 if (index() == CodeBuffer::locator_sect(loc)) { | |
288 return start() + CodeBuffer::locator_pos(loc); | |
289 } else { | |
290 return outer()->locator_address(loc); | |
291 } | |
292 } else { | |
293 assert(allocates2(branch_pc), "sanity"); | |
294 address base = start(); | |
295 int patch_loc = CodeBuffer::locator(branch_pc - base, index()); | |
296 L.add_patch_at(outer(), patch_loc); | |
297 | |
298 // Need to return a pc, doesn't matter what it is since it will be | |
299 // replaced during resolution later. | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
300 // Don't return NULL or badAddress, since branches shouldn't overflow. |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
301 // Don't return base either because that could overflow displacements |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
302 // for shorter branches. It will get checked when bound. |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
303 return branch_pc; |
0 | 304 } |
305 } | |
306 | |
307 void CodeSection::relocate(address at, RelocationHolder const& spec, int format) { | |
308 Relocation* reloc = spec.reloc(); | |
309 relocInfo::relocType rtype = (relocInfo::relocType) reloc->type(); | |
310 if (rtype == relocInfo::none) return; | |
311 | |
312 // The assertion below has been adjusted, to also work for | |
313 // relocation for fixup. Sometimes we want to put relocation | |
314 // information for the next instruction, since it will be patched | |
315 // with a call. | |
316 assert(start() <= at && at <= end()+1, | |
317 "cannot relocate data outside code boundaries"); | |
318 | |
319 if (!has_locs()) { | |
320 // no space for relocation information provided => code cannot be | |
321 // relocated. Make sure that relocate is only called with rtypes | |
322 // that can be ignored for this kind of code. | |
323 assert(rtype == relocInfo::none || | |
324 rtype == relocInfo::runtime_call_type || | |
325 rtype == relocInfo::internal_word_type|| | |
326 rtype == relocInfo::section_word_type || | |
327 rtype == relocInfo::external_word_type, | |
328 "code needs relocation information"); | |
329 // leave behind an indication that we attempted a relocation | |
330 DEBUG_ONLY(_locs_start = _locs_limit = (relocInfo*)badAddress); | |
331 return; | |
332 } | |
333 | |
334 // Advance the point, noting the offset we'll have to record. | |
335 csize_t offset = at - locs_point(); | |
336 set_locs_point(at); | |
337 | |
338 // Test for a couple of overflow conditions; maybe expand the buffer. | |
339 relocInfo* end = locs_end(); | |
340 relocInfo* req = end + relocInfo::length_limit; | |
341 // Check for (potential) overflow | |
342 if (req >= locs_limit() || offset >= relocInfo::offset_limit()) { | |
343 req += (uint)offset / (uint)relocInfo::offset_limit(); | |
344 if (req >= locs_limit()) { | |
345 // Allocate or reallocate. | |
346 expand_locs(locs_count() + (req - end)); | |
347 // reload pointer | |
348 end = locs_end(); | |
349 } | |
350 } | |
351 | |
352 // If the offset is giant, emit filler relocs, of type 'none', but | |
353 // each carrying the largest possible offset, to advance the locs_point. | |
354 while (offset >= relocInfo::offset_limit()) { | |
355 assert(end < locs_limit(), "adjust previous paragraph of code"); | |
356 *end++ = filler_relocInfo(); | |
357 offset -= filler_relocInfo().addr_offset(); | |
358 } | |
359 | |
360 // If it's a simple reloc with no data, we'll just write (rtype | offset). | |
361 (*end) = relocInfo(rtype, offset, format); | |
362 | |
363 // If it has data, insert the prefix, as (data_prefix_tag | data1), data2. | |
364 end->initialize(this, reloc); | |
365 } | |
366 | |
367 void CodeSection::initialize_locs(int locs_capacity) { | |
368 assert(_locs_start == NULL, "only one locs init step, please"); | |
369 // Apply a priori lower limits to relocation size: | |
370 csize_t min_locs = MAX2(size() / 16, (csize_t)4); | |
371 if (locs_capacity < min_locs) locs_capacity = min_locs; | |
372 relocInfo* locs_start = NEW_RESOURCE_ARRAY(relocInfo, locs_capacity); | |
373 _locs_start = locs_start; | |
374 _locs_end = locs_start; | |
375 _locs_limit = locs_start + locs_capacity; | |
376 _locs_own = true; | |
377 } | |
378 | |
379 void CodeSection::initialize_shared_locs(relocInfo* buf, int length) { | |
380 assert(_locs_start == NULL, "do this before locs are allocated"); | |
381 // Internal invariant: locs buf must be fully aligned. | |
382 // See copy_relocations_to() below. | |
383 while ((uintptr_t)buf % HeapWordSize != 0 && length > 0) { | |
384 ++buf; --length; | |
385 } | |
386 if (length > 0) { | |
387 _locs_start = buf; | |
388 _locs_end = buf; | |
389 _locs_limit = buf + length; | |
390 _locs_own = false; | |
391 } | |
392 } | |
393 | |
394 void CodeSection::initialize_locs_from(const CodeSection* source_cs) { | |
395 int lcount = source_cs->locs_count(); | |
396 if (lcount != 0) { | |
397 initialize_shared_locs(source_cs->locs_start(), lcount); | |
398 _locs_end = _locs_limit = _locs_start + lcount; | |
399 assert(is_allocated(), "must have copied code already"); | |
400 set_locs_point(start() + source_cs->locs_point_off()); | |
401 } | |
402 assert(this->locs_count() == source_cs->locs_count(), "sanity"); | |
403 } | |
404 | |
405 void CodeSection::expand_locs(int new_capacity) { | |
406 if (_locs_start == NULL) { | |
407 initialize_locs(new_capacity); | |
408 return; | |
409 } else { | |
410 int old_count = locs_count(); | |
411 int old_capacity = locs_capacity(); | |
412 if (new_capacity < old_capacity * 2) | |
413 new_capacity = old_capacity * 2; | |
414 relocInfo* locs_start; | |
415 if (_locs_own) { | |
416 locs_start = REALLOC_RESOURCE_ARRAY(relocInfo, _locs_start, old_capacity, new_capacity); | |
417 } else { | |
418 locs_start = NEW_RESOURCE_ARRAY(relocInfo, new_capacity); | |
1603
d93949c5bdcc
6730276: JDI_REGRESSION tests fail with "Error: count must be non-zero" error on x86
kvn
parents:
1552
diff
changeset
|
419 Copy::conjoint_jbytes(_locs_start, locs_start, old_capacity * sizeof(relocInfo)); |
0 | 420 _locs_own = true; |
421 } | |
422 _locs_start = locs_start; | |
423 _locs_end = locs_start + old_count; | |
424 _locs_limit = locs_start + new_capacity; | |
425 } | |
426 } | |
427 | |
428 | |
429 /// Support for emitting the code to its final location. | |
430 /// The pattern is the same for all functions. | |
431 /// We iterate over all the sections, padding each to alignment. | |
432 | |
1748 | 433 csize_t CodeBuffer::total_content_size() const { |
434 csize_t size_so_far = 0; | |
0 | 435 for (int n = 0; n < (int)SECT_LIMIT; n++) { |
436 const CodeSection* cs = code_section(n); | |
437 if (cs->is_empty()) continue; // skip trivial section | |
1748 | 438 size_so_far = cs->align_at_start(size_so_far); |
439 size_so_far += cs->size(); | |
0 | 440 } |
1748 | 441 return size_so_far; |
0 | 442 } |
443 | |
444 void CodeBuffer::compute_final_layout(CodeBuffer* dest) const { | |
445 address buf = dest->_total_start; | |
446 csize_t buf_offset = 0; | |
1748 | 447 assert(dest->_total_size >= total_content_size(), "must be big enough"); |
0 | 448 |
449 { | |
450 // not sure why this is here, but why not... | |
451 int alignSize = MAX2((intx) sizeof(jdouble), CodeEntryAlignment); | |
452 assert( (dest->_total_start - _insts.start()) % alignSize == 0, "copy must preserve alignment"); | |
453 } | |
454 | |
455 const CodeSection* prev_cs = NULL; | |
456 CodeSection* prev_dest_cs = NULL; | |
1762
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
457 |
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
458 for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) { |
0 | 459 // figure compact layout of each section |
460 const CodeSection* cs = code_section(n); | |
1762
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
461 csize_t csize = cs->size(); |
0 | 462 |
463 CodeSection* dest_cs = dest->code_section(n); | |
464 if (!cs->is_empty()) { | |
465 // Compute initial padding; assign it to the previous non-empty guy. | |
466 // Cf. figure_expanded_capacities. | |
467 csize_t padding = cs->align_at_start(buf_offset) - buf_offset; | |
468 if (padding != 0) { | |
469 buf_offset += padding; | |
470 assert(prev_dest_cs != NULL, "sanity"); | |
471 prev_dest_cs->_limit += padding; | |
472 } | |
473 #ifdef ASSERT | |
1762
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
474 if (prev_cs != NULL && prev_cs->is_frozen() && n < (SECT_LIMIT - 1)) { |
0 | 475 // Make sure the ends still match up. |
476 // This is important because a branch in a frozen section | |
477 // might target code in a following section, via a Label, | |
478 // and without a relocation record. See Label::patch_instructions. | |
479 address dest_start = buf+buf_offset; | |
480 csize_t start2start = cs->start() - prev_cs->start(); | |
481 csize_t dest_start2start = dest_start - prev_dest_cs->start(); | |
482 assert(start2start == dest_start2start, "cannot stretch frozen sect"); | |
483 } | |
484 #endif //ASSERT | |
485 prev_dest_cs = dest_cs; | |
486 prev_cs = cs; | |
487 } | |
488 | |
489 debug_only(dest_cs->_start = NULL); // defeat double-initialization assert | |
490 dest_cs->initialize(buf+buf_offset, csize); | |
491 dest_cs->set_end(buf+buf_offset+csize); | |
492 assert(dest_cs->is_allocated(), "must always be allocated"); | |
493 assert(cs->is_empty() == dest_cs->is_empty(), "sanity"); | |
494 | |
495 buf_offset += csize; | |
496 } | |
497 | |
498 // Done calculating sections; did it come out to the right end? | |
1748 | 499 assert(buf_offset == total_content_size(), "sanity"); |
4059
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
500 dest->verify_section_allocation(); |
0 | 501 } |
502 | |
7409 | 503 // Append an oop reference that keeps the class alive. |
7185
90273fc0a981
8000662: NPG: nashorn ant clean test262 out-of-memory with Java heap
coleenp
parents:
6926
diff
changeset
|
504 static void append_oop_references(GrowableArray<oop>* oops, Klass* k) { |
7409 | 505 oop cl = k->klass_holder(); |
7185
90273fc0a981
8000662: NPG: nashorn ant clean test262 out-of-memory with Java heap
coleenp
parents:
6926
diff
changeset
|
506 if (cl != NULL && !oops->contains(cl)) { |
90273fc0a981
8000662: NPG: nashorn ant clean test262 out-of-memory with Java heap
coleenp
parents:
6926
diff
changeset
|
507 oops->append(cl); |
90273fc0a981
8000662: NPG: nashorn ant clean test262 out-of-memory with Java heap
coleenp
parents:
6926
diff
changeset
|
508 } |
90273fc0a981
8000662: NPG: nashorn ant clean test262 out-of-memory with Java heap
coleenp
parents:
6926
diff
changeset
|
509 } |
90273fc0a981
8000662: NPG: nashorn ant clean test262 out-of-memory with Java heap
coleenp
parents:
6926
diff
changeset
|
510 |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
511 void CodeBuffer::finalize_oop_references(methodHandle mh) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
512 No_Safepoint_Verifier nsv; |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
513 |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
514 GrowableArray<oop> oops; |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
515 |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
516 // Make sure that immediate metadata records something in the OopRecorder |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
517 for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
518 // pull code out of each section |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
519 CodeSection* cs = code_section(n); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
520 if (cs->is_empty()) continue; // skip trivial section |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
521 RelocIterator iter(cs); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
522 while (iter.next()) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
523 if (iter.type() == relocInfo::metadata_type) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
524 metadata_Relocation* md = iter.metadata_reloc(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
525 if (md->metadata_is_immediate()) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
526 Metadata* m = md->metadata_value(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
527 if (oop_recorder()->is_real(m)) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
528 if (m->is_methodData()) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
529 m = ((MethodData*)m)->method(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
530 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
531 if (m->is_method()) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
532 m = ((Method*)m)->method_holder(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
533 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
534 if (m->is_klass()) { |
7185
90273fc0a981
8000662: NPG: nashorn ant clean test262 out-of-memory with Java heap
coleenp
parents:
6926
diff
changeset
|
535 append_oop_references(&oops, (Klass*)m); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
536 } else { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
537 // XXX This will currently occur for MDO which don't |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
538 // have a backpointer. This has to be fixed later. |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
539 m->print(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
540 ShouldNotReachHere(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
541 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
542 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
543 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
544 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
545 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
546 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
547 |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
548 if (!oop_recorder()->is_unused()) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
549 for (int i = 0; i < oop_recorder()->metadata_count(); i++) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
550 Metadata* m = oop_recorder()->metadata_at(i); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
551 if (oop_recorder()->is_real(m)) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
552 if (m->is_methodData()) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
553 m = ((MethodData*)m)->method(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
554 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
555 if (m->is_method()) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
556 m = ((Method*)m)->method_holder(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
557 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
558 if (m->is_klass()) { |
7185
90273fc0a981
8000662: NPG: nashorn ant clean test262 out-of-memory with Java heap
coleenp
parents:
6926
diff
changeset
|
559 append_oop_references(&oops, (Klass*)m); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
560 } else { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
561 m->print(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
562 ShouldNotReachHere(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
563 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
564 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
565 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
566 |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
567 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
568 |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
569 // Add the class loader of Method* for the nmethod itself |
7185
90273fc0a981
8000662: NPG: nashorn ant clean test262 out-of-memory with Java heap
coleenp
parents:
6926
diff
changeset
|
570 append_oop_references(&oops, mh->method_holder()); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
571 |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
572 // Add any oops that we've found |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
573 Thread* thread = Thread::current(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
574 for (int i = 0; i < oops.length(); i++) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
575 oop_recorder()->find_index((jobject)thread->handle_area()->allocate_handle(oops.at(i))); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
576 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
577 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
578 |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
579 |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
580 |
1762
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
581 csize_t CodeBuffer::total_offset_of(CodeSection* cs) const { |
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
582 csize_t size_so_far = 0; |
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
583 for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) { |
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
584 const CodeSection* cur_cs = code_section(n); |
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
585 if (!cur_cs->is_empty()) { |
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
586 size_so_far = cur_cs->align_at_start(size_so_far); |
0 | 587 } |
1762
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
588 if (cur_cs->index() == cs->index()) { |
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
589 return size_so_far; |
0 | 590 } |
1762
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
591 size_so_far += cur_cs->size(); |
0 | 592 } |
593 ShouldNotReachHere(); | |
594 return -1; | |
595 } | |
596 | |
597 csize_t CodeBuffer::total_relocation_size() const { | |
598 csize_t lsize = copy_relocations_to(NULL); // dry run only | |
1748 | 599 csize_t csize = total_content_size(); |
0 | 600 csize_t total = RelocIterator::locs_and_index_size(csize, lsize); |
601 return (csize_t) align_size_up(total, HeapWordSize); | |
602 } | |
603 | |
604 csize_t CodeBuffer::copy_relocations_to(CodeBlob* dest) const { | |
605 address buf = NULL; | |
606 csize_t buf_offset = 0; | |
607 csize_t buf_limit = 0; | |
608 if (dest != NULL) { | |
609 buf = (address)dest->relocation_begin(); | |
610 buf_limit = (address)dest->relocation_end() - buf; | |
611 assert((uintptr_t)buf % HeapWordSize == 0, "buf must be fully aligned"); | |
612 assert(buf_limit % HeapWordSize == 0, "buf must be evenly sized"); | |
613 } | |
614 // if dest == NULL, this is just the sizing pass | |
615 | |
616 csize_t code_end_so_far = 0; | |
617 csize_t code_point_so_far = 0; | |
1762
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
618 for (int n = (int) SECT_FIRST; n < (int)SECT_LIMIT; n++) { |
0 | 619 // pull relocs out of each section |
620 const CodeSection* cs = code_section(n); | |
621 assert(!(cs->is_empty() && cs->locs_count() > 0), "sanity"); | |
622 if (cs->is_empty()) continue; // skip trivial section | |
623 relocInfo* lstart = cs->locs_start(); | |
624 relocInfo* lend = cs->locs_end(); | |
625 csize_t lsize = (csize_t)( (address)lend - (address)lstart ); | |
626 csize_t csize = cs->size(); | |
627 code_end_so_far = cs->align_at_start(code_end_so_far); | |
628 | |
629 if (lsize > 0) { | |
630 // Figure out how to advance the combined relocation point | |
631 // first to the beginning of this section. | |
632 // We'll insert one or more filler relocs to span that gap. | |
633 // (Don't bother to improve this by editing the first reloc's offset.) | |
634 csize_t new_code_point = code_end_so_far; | |
635 for (csize_t jump; | |
636 code_point_so_far < new_code_point; | |
637 code_point_so_far += jump) { | |
638 jump = new_code_point - code_point_so_far; | |
639 relocInfo filler = filler_relocInfo(); | |
640 if (jump >= filler.addr_offset()) { | |
641 jump = filler.addr_offset(); | |
642 } else { // else shrink the filler to fit | |
643 filler = relocInfo(relocInfo::none, jump); | |
644 } | |
645 if (buf != NULL) { | |
646 assert(buf_offset + (csize_t)sizeof(filler) <= buf_limit, "filler in bounds"); | |
647 *(relocInfo*)(buf+buf_offset) = filler; | |
648 } | |
649 buf_offset += sizeof(filler); | |
650 } | |
651 | |
652 // Update code point and end to skip past this section: | |
653 csize_t last_code_point = code_end_so_far + cs->locs_point_off(); | |
654 assert(code_point_so_far <= last_code_point, "sanity"); | |
655 code_point_so_far = last_code_point; // advance past this guy's relocs | |
656 } | |
657 code_end_so_far += csize; // advance past this guy's instructions too | |
658 | |
659 // Done with filler; emit the real relocations: | |
660 if (buf != NULL && lsize != 0) { | |
661 assert(buf_offset + lsize <= buf_limit, "target in bounds"); | |
662 assert((uintptr_t)lstart % HeapWordSize == 0, "sane start"); | |
663 if (buf_offset % HeapWordSize == 0) { | |
664 // Use wordwise copies if possible: | |
665 Copy::disjoint_words((HeapWord*)lstart, | |
666 (HeapWord*)(buf+buf_offset), | |
667 (lsize + HeapWordSize-1) / HeapWordSize); | |
668 } else { | |
1603
d93949c5bdcc
6730276: JDI_REGRESSION tests fail with "Error: count must be non-zero" error on x86
kvn
parents:
1552
diff
changeset
|
669 Copy::conjoint_jbytes(lstart, buf+buf_offset, lsize); |
0 | 670 } |
671 } | |
672 buf_offset += lsize; | |
673 } | |
674 | |
675 // Align end of relocation info in target. | |
676 while (buf_offset % HeapWordSize != 0) { | |
677 if (buf != NULL) { | |
678 relocInfo padding = relocInfo(relocInfo::none, 0); | |
679 assert(buf_offset + (csize_t)sizeof(padding) <= buf_limit, "padding in bounds"); | |
680 *(relocInfo*)(buf+buf_offset) = padding; | |
681 } | |
682 buf_offset += sizeof(relocInfo); | |
683 } | |
684 | |
1748 | 685 assert(code_end_so_far == total_content_size(), "sanity"); |
0 | 686 |
687 // Account for index: | |
688 if (buf != NULL) { | |
689 RelocIterator::create_index(dest->relocation_begin(), | |
690 buf_offset / sizeof(relocInfo), | |
691 dest->relocation_end()); | |
692 } | |
693 | |
694 return buf_offset; | |
695 } | |
696 | |
697 void CodeBuffer::copy_code_to(CodeBlob* dest_blob) { | |
698 #ifndef PRODUCT | |
699 if (PrintNMethods && (WizardMode || Verbose)) { | |
700 tty->print("done with CodeBuffer:"); | |
701 ((CodeBuffer*)this)->print(); | |
702 } | |
703 #endif //PRODUCT | |
704 | |
1748 | 705 CodeBuffer dest(dest_blob); |
706 assert(dest_blob->content_size() >= total_content_size(), "good sizing"); | |
0 | 707 this->compute_final_layout(&dest); |
708 relocate_code_to(&dest); | |
709 | |
8767
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
710 // transfer strings and comments from buffer to blob |
20435 | 711 dest_blob->set_strings(_code_strings); |
0 | 712 |
713 // Done moving code bytes; were they the right size? | |
1748 | 714 assert(round_to(dest.total_content_size(), oopSize) == dest_blob->content_size(), "sanity"); |
0 | 715 |
716 // Flush generated code | |
1748 | 717 ICache::invalidate_range(dest_blob->code_begin(), dest_blob->code_size()); |
0 | 718 } |
719 | |
1762
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
720 // Move all my code into another code buffer. Consult applicable |
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
721 // relocs to repair embedded addresses. The layout in the destination |
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
722 // CodeBuffer is different to the source CodeBuffer: the destination |
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
723 // CodeBuffer gets the final layout (consts, insts, stubs in order of |
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
724 // ascending address). |
0 | 725 void CodeBuffer::relocate_code_to(CodeBuffer* dest) const { |
4040
754110e02bd5
7103380: assertion failure with -XX:+PrintNativeNMethods
never
parents:
2015
diff
changeset
|
726 address dest_end = dest->_total_start + dest->_total_size; |
754110e02bd5
7103380: assertion failure with -XX:+PrintNativeNMethods
never
parents:
2015
diff
changeset
|
727 address dest_filled = NULL; |
1762
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
728 for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) { |
0 | 729 // pull code out of each section |
730 const CodeSection* cs = code_section(n); | |
731 if (cs->is_empty()) continue; // skip trivial section | |
732 CodeSection* dest_cs = dest->code_section(n); | |
733 assert(cs->size() == dest_cs->size(), "sanity"); | |
734 csize_t usize = dest_cs->size(); | |
735 csize_t wsize = align_size_up(usize, HeapWordSize); | |
736 assert(dest_cs->start() + wsize <= dest_end, "no overflow"); | |
737 // Copy the code as aligned machine words. | |
738 // This may also include an uninitialized partial word at the end. | |
739 Copy::disjoint_words((HeapWord*)cs->start(), | |
740 (HeapWord*)dest_cs->start(), | |
741 wsize / HeapWordSize); | |
742 | |
743 if (dest->blob() == NULL) { | |
744 // Destination is a final resting place, not just another buffer. | |
745 // Normalize uninitialized bytes in the final padding. | |
746 Copy::fill_to_bytes(dest_cs->end(), dest_cs->remaining(), | |
747 Assembler::code_fill_byte()); | |
748 } | |
4040
754110e02bd5
7103380: assertion failure with -XX:+PrintNativeNMethods
never
parents:
2015
diff
changeset
|
749 // Keep track of the highest filled address |
754110e02bd5
7103380: assertion failure with -XX:+PrintNativeNMethods
never
parents:
2015
diff
changeset
|
750 dest_filled = MAX2(dest_filled, dest_cs->end() + dest_cs->remaining()); |
0 | 751 |
752 assert(cs->locs_start() != (relocInfo*)badAddress, | |
753 "this section carries no reloc storage, but reloc was attempted"); | |
754 | |
755 // Make the new code copy use the old copy's relocations: | |
756 dest_cs->initialize_locs_from(cs); | |
7197 | 757 } |
0 | 758 |
7197 | 759 // Do relocation after all sections are copied. |
760 // This is necessary if the code uses constants in stubs, which are | |
761 // relocated when the corresponding instruction in the code (e.g., a | |
762 // call) is relocated. Stubs are placed behind the main code | |
763 // section, so that section has to be copied before relocating. | |
764 for (int n = (int) SECT_FIRST; n < (int)SECT_LIMIT; n++) { | |
765 // pull code out of each section | |
766 const CodeSection* cs = code_section(n); | |
767 if (cs->is_empty()) continue; // skip trivial section | |
768 CodeSection* dest_cs = dest->code_section(n); | |
0 | 769 { // Repair the pc relative information in the code after the move |
770 RelocIterator iter(dest_cs); | |
771 while (iter.next()) { | |
772 iter.reloc()->fix_relocation_after_move(this, dest); | |
773 } | |
774 } | |
775 } | |
4040
754110e02bd5
7103380: assertion failure with -XX:+PrintNativeNMethods
never
parents:
2015
diff
changeset
|
776 |
6926 | 777 if (dest->blob() == NULL && dest_filled != NULL) { |
4040
754110e02bd5
7103380: assertion failure with -XX:+PrintNativeNMethods
never
parents:
2015
diff
changeset
|
778 // Destination is a final resting place, not just another buffer. |
754110e02bd5
7103380: assertion failure with -XX:+PrintNativeNMethods
never
parents:
2015
diff
changeset
|
779 // Normalize uninitialized bytes in the final padding. |
754110e02bd5
7103380: assertion failure with -XX:+PrintNativeNMethods
never
parents:
2015
diff
changeset
|
780 Copy::fill_to_bytes(dest_filled, dest_end - dest_filled, |
754110e02bd5
7103380: assertion failure with -XX:+PrintNativeNMethods
never
parents:
2015
diff
changeset
|
781 Assembler::code_fill_byte()); |
754110e02bd5
7103380: assertion failure with -XX:+PrintNativeNMethods
never
parents:
2015
diff
changeset
|
782 |
754110e02bd5
7103380: assertion failure with -XX:+PrintNativeNMethods
never
parents:
2015
diff
changeset
|
783 } |
0 | 784 } |
785 | |
786 csize_t CodeBuffer::figure_expanded_capacities(CodeSection* which_cs, | |
787 csize_t amount, | |
788 csize_t* new_capacity) { | |
789 csize_t new_total_cap = 0; | |
790 | |
1762
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
791 for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) { |
0 | 792 const CodeSection* sect = code_section(n); |
793 | |
794 if (!sect->is_empty()) { | |
1762
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
795 // Compute initial padding; assign it to the previous section, |
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
796 // even if it's empty (e.g. consts section can be empty). |
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
797 // Cf. compute_final_layout |
0 | 798 csize_t padding = sect->align_at_start(new_total_cap) - new_total_cap; |
799 if (padding != 0) { | |
800 new_total_cap += padding; | |
1762
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
801 assert(n - 1 >= SECT_FIRST, "sanity"); |
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
802 new_capacity[n - 1] += padding; |
0 | 803 } |
804 } | |
805 | |
806 csize_t exp = sect->size(); // 100% increase | |
807 if ((uint)exp < 4*K) exp = 4*K; // minimum initial increase | |
808 if (sect == which_cs) { | |
809 if (exp < amount) exp = amount; | |
810 if (StressCodeBuffers) exp = amount; // expand only slightly | |
811 } else if (n == SECT_INSTS) { | |
812 // scale down inst increases to a more modest 25% | |
813 exp = 4*K + ((exp - 4*K) >> 2); | |
814 if (StressCodeBuffers) exp = amount / 2; // expand only slightly | |
815 } else if (sect->is_empty()) { | |
816 // do not grow an empty secondary section | |
817 exp = 0; | |
818 } | |
819 // Allow for inter-section slop: | |
820 exp += CodeSection::end_slop(); | |
821 csize_t new_cap = sect->size() + exp; | |
822 if (new_cap < sect->capacity()) { | |
823 // No need to expand after all. | |
824 new_cap = sect->capacity(); | |
825 } | |
826 new_capacity[n] = new_cap; | |
827 new_total_cap += new_cap; | |
828 } | |
829 | |
830 return new_total_cap; | |
831 } | |
832 | |
833 void CodeBuffer::expand(CodeSection* which_cs, csize_t amount) { | |
834 #ifndef PRODUCT | |
835 if (PrintNMethods && (WizardMode || Verbose)) { | |
836 tty->print("expanding CodeBuffer:"); | |
837 this->print(); | |
838 } | |
839 | |
840 if (StressCodeBuffers && blob() != NULL) { | |
841 static int expand_count = 0; | |
842 if (expand_count >= 0) expand_count += 1; | |
843 if (expand_count > 100 && is_power_of_2(expand_count)) { | |
844 tty->print_cr("StressCodeBuffers: have expanded %d times", expand_count); | |
845 // simulate an occasional allocation failure: | |
846 free_blob(); | |
847 } | |
848 } | |
849 #endif //PRODUCT | |
850 | |
851 // Resizing must be allowed | |
852 { | |
853 if (blob() == NULL) return; // caller must check for blob == NULL | |
854 for (int n = 0; n < (int)SECT_LIMIT; n++) { | |
855 guarantee(!code_section(n)->is_frozen(), "resizing not allowed when frozen"); | |
856 } | |
857 } | |
858 | |
859 // Figure new capacity for each section. | |
860 csize_t new_capacity[SECT_LIMIT]; | |
861 csize_t new_total_cap | |
862 = figure_expanded_capacities(which_cs, amount, new_capacity); | |
863 | |
864 // Create a new (temporary) code buffer to hold all the new data | |
865 CodeBuffer cb(name(), new_total_cap, 0); | |
866 if (cb.blob() == NULL) { | |
867 // Failed to allocate in code cache. | |
868 free_blob(); | |
869 return; | |
870 } | |
871 | |
872 // Create an old code buffer to remember which addresses used to go where. | |
873 // This will be useful when we do final assembly into the code cache, | |
874 // because we will need to know how to warp any internal address that | |
875 // has been created at any time in this CodeBuffer's past. | |
876 CodeBuffer* bxp = new CodeBuffer(_total_start, _total_size); | |
877 bxp->take_over_code_from(this); // remember the old undersized blob | |
878 DEBUG_ONLY(this->_blob = NULL); // silence a later assert | |
879 bxp->_before_expand = this->_before_expand; | |
880 this->_before_expand = bxp; | |
881 | |
882 // Give each section its required (expanded) capacity. | |
1762
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
883 for (int n = (int)SECT_LIMIT-1; n >= SECT_FIRST; n--) { |
0 | 884 CodeSection* cb_sect = cb.code_section(n); |
885 CodeSection* this_sect = code_section(n); | |
886 if (new_capacity[n] == 0) continue; // already nulled out | |
1762
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
887 if (n != SECT_INSTS) { |
0 | 888 cb.initialize_section_size(cb_sect, new_capacity[n]); |
889 } | |
890 assert(cb_sect->capacity() >= new_capacity[n], "big enough"); | |
891 address cb_start = cb_sect->start(); | |
892 cb_sect->set_end(cb_start + this_sect->size()); | |
893 if (this_sect->mark() == NULL) { | |
894 cb_sect->clear_mark(); | |
895 } else { | |
896 cb_sect->set_mark(cb_start + this_sect->mark_off()); | |
897 } | |
898 } | |
899 | |
900 // Move all the code and relocations to the new blob: | |
901 relocate_code_to(&cb); | |
902 | |
903 // Copy the temporary code buffer into the current code buffer. | |
904 // Basically, do {*this = cb}, except for some control information. | |
905 this->take_over_code_from(&cb); | |
906 cb.set_blob(NULL); | |
907 | |
908 // Zap the old code buffer contents, to avoid mistakenly using them. | |
909 debug_only(Copy::fill_to_bytes(bxp->_total_start, bxp->_total_size, | |
910 badCodeHeapFreeVal)); | |
911 | |
912 _decode_begin = NULL; // sanity | |
913 | |
914 // Make certain that the new sections are all snugly inside the new blob. | |
4059
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
915 verify_section_allocation(); |
0 | 916 |
917 #ifndef PRODUCT | |
918 if (PrintNMethods && (WizardMode || Verbose)) { | |
919 tty->print("expanded CodeBuffer:"); | |
920 this->print(); | |
921 } | |
922 #endif //PRODUCT | |
923 } | |
924 | |
925 void CodeBuffer::take_over_code_from(CodeBuffer* cb) { | |
926 // Must already have disposed of the old blob somehow. | |
927 assert(blob() == NULL, "must be empty"); | |
928 #ifdef ASSERT | |
929 | |
930 #endif | |
931 // Take the new blob away from cb. | |
932 set_blob(cb->blob()); | |
933 // Take over all the section pointers. | |
934 for (int n = 0; n < (int)SECT_LIMIT; n++) { | |
935 CodeSection* cb_sect = cb->code_section(n); | |
936 CodeSection* this_sect = code_section(n); | |
937 this_sect->take_over_code_from(cb_sect); | |
938 } | |
939 _overflow_arena = cb->_overflow_arena; | |
940 // Make sure the old cb won't try to use it or free it. | |
941 DEBUG_ONLY(cb->_blob = (BufferBlob*)badAddress); | |
942 } | |
943 | |
4059
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
944 void CodeBuffer::verify_section_allocation() { |
0 | 945 address tstart = _total_start; |
4059
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
946 if (tstart == badAddress) return; // smashed by set_blob(NULL) |
0 | 947 address tend = tstart + _total_size; |
948 if (_blob != NULL) { | |
4059
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
949 |
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
950 guarantee(tstart >= _blob->content_begin(), "sanity"); |
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
951 guarantee(tend <= _blob->content_end(), "sanity"); |
0 | 952 } |
1762
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
953 // Verify disjointness. |
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
954 for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) { |
0 | 955 CodeSection* sect = code_section(n); |
1762
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
956 if (!sect->is_allocated() || sect->is_empty()) continue; |
4059
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
957 guarantee((intptr_t)sect->start() % sect->alignment() == 0 |
0 | 958 || sect->is_empty() || _blob == NULL, |
959 "start is aligned"); | |
1762
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
960 for (int m = (int) SECT_FIRST; m < (int) SECT_LIMIT; m++) { |
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
961 CodeSection* other = code_section(m); |
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
962 if (!other->is_allocated() || other == sect) continue; |
4059
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
963 guarantee(!other->contains(sect->start() ), "sanity"); |
1762
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
964 // limit is an exclusive address and can be the start of another |
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
965 // section. |
4059
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
966 guarantee(!other->contains(sect->limit() - 1), "sanity"); |
1762
0878d7bae69f
6961697: move nmethod constants section before instruction section
twisti
parents:
1748
diff
changeset
|
967 } |
4059
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
968 guarantee(sect->end() <= tend, "sanity"); |
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
969 guarantee(sect->end() <= sect->limit(), "sanity"); |
0 | 970 } |
971 } | |
4059
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
972 |
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
973 void CodeBuffer::log_section_sizes(const char* name) { |
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
974 if (xtty != NULL) { |
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
975 // log info about buffer usage |
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
976 xtty->print_cr("<blob name='%s' size='%d'>", name, _total_size); |
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
977 for (int n = (int) CodeBuffer::SECT_FIRST; n < (int) CodeBuffer::SECT_LIMIT; n++) { |
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
978 CodeSection* sect = code_section(n); |
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
979 if (!sect->is_allocated() || sect->is_empty()) continue; |
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
980 xtty->print_cr("<sect index='%d' size='" SIZE_FORMAT "' free='" SIZE_FORMAT "'/>", |
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
981 n, sect->limit() - sect->start(), sect->limit() - sect->end()); |
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
982 } |
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
983 xtty->print_cr("</blob>"); |
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
984 } |
44ce519bc3d1
7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer
never
parents:
4040
diff
changeset
|
985 } |
0 | 986 |
987 #ifndef PRODUCT | |
988 | |
989 void CodeSection::dump() { | |
990 address ptr = start(); | |
991 for (csize_t step; ptr < end(); ptr += step) { | |
992 step = end() - ptr; | |
993 if (step > jintSize * 4) step = jintSize * 4; | |
17937
78bbf4d43a14
8037816: Fix for 8036122 breaks build with Xcode5/clang
drchase
parents:
17467
diff
changeset
|
994 tty->print(INTPTR_FORMAT ": ", p2i(ptr)); |
0 | 995 while (step > 0) { |
996 tty->print(" " PTR32_FORMAT, *(jint*)ptr); | |
997 ptr += jintSize; | |
998 } | |
999 tty->cr(); | |
1000 } | |
1001 } | |
1002 | |
1003 | |
1004 void CodeSection::decode() { | |
1005 Disassembler::decode(start(), end()); | |
1006 } | |
1007 | |
1008 | |
1009 void CodeBuffer::block_comment(intptr_t offset, const char * comment) { | |
20435 | 1010 _code_strings.add_comment(offset, comment); |
8767
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1011 } |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1012 |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1013 const char* CodeBuffer::code_string(const char* str) { |
20435 | 1014 return _code_strings.add_string(str); |
0 | 1015 } |
1016 | |
8767
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1017 class CodeString: public CHeapObj<mtCode> { |
0 | 1018 private: |
8767
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1019 friend class CodeStrings; |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1020 const char * _string; |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1021 CodeString* _next; |
0 | 1022 intptr_t _offset; |
1023 | |
8767
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1024 ~CodeString() { |
0 | 1025 assert(_next == NULL, "wrong interface for freeing list"); |
8767
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1026 os::free((void*)_string, mtCode); |
0 | 1027 } |
1028 | |
8767
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1029 bool is_comment() const { return _offset >= 0; } |
0 | 1030 |
8767
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1031 public: |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1032 CodeString(const char * string, intptr_t offset = -1) |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1033 : _next(NULL), _offset(offset) { |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1034 _string = os::strdup(string, mtCode); |
0 | 1035 } |
6796
b31471cdc53e
7200163: add CodeComments functionality to assember stubs
kvn
parents:
6725
diff
changeset
|
1036 |
8767
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1037 const char * string() const { return _string; } |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1038 intptr_t offset() const { assert(_offset >= 0, "offset for non comment?"); return _offset; } |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1039 CodeString* next() const { return _next; } |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1040 |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1041 void set_next(CodeString* next) { _next = next; } |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1042 |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1043 CodeString* first_comment() { |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1044 if (is_comment()) { |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1045 return this; |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1046 } else { |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1047 return next_comment(); |
6796
b31471cdc53e
7200163: add CodeComments functionality to assember stubs
kvn
parents:
6725
diff
changeset
|
1048 } |
8767
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1049 } |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1050 CodeString* next_comment() const { |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1051 CodeString* s = _next; |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1052 while (s != NULL && !s->is_comment()) { |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1053 s = s->_next; |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1054 } |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1055 return s; |
6796
b31471cdc53e
7200163: add CodeComments functionality to assember stubs
kvn
parents:
6725
diff
changeset
|
1056 } |
0 | 1057 }; |
1058 | |
8767
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1059 CodeString* CodeStrings::find(intptr_t offset) const { |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1060 CodeString* a = _strings->first_comment(); |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1061 while (a != NULL && a->offset() != offset) { |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1062 a = a->next_comment(); |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1063 } |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1064 return a; |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1065 } |
0 | 1066 |
8767
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1067 // Convenience for add_comment. |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1068 CodeString* CodeStrings::find_last(intptr_t offset) const { |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1069 CodeString* a = find(offset); |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1070 if (a != NULL) { |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1071 CodeString* c = NULL; |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1072 while (((c = a->next_comment()) != NULL) && (c->offset() == offset)) { |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1073 a = c; |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1074 } |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1075 } |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1076 return a; |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1077 } |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1078 |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1079 void CodeStrings::add_comment(intptr_t offset, const char * comment) { |
20435 | 1080 check_valid(); |
8767
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1081 CodeString* c = new CodeString(comment, offset); |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1082 CodeString* inspos = (_strings == NULL) ? NULL : find_last(offset); |
6796
b31471cdc53e
7200163: add CodeComments functionality to assember stubs
kvn
parents:
6725
diff
changeset
|
1083 |
b31471cdc53e
7200163: add CodeComments functionality to assember stubs
kvn
parents:
6725
diff
changeset
|
1084 if (inspos) { |
b31471cdc53e
7200163: add CodeComments functionality to assember stubs
kvn
parents:
6725
diff
changeset
|
1085 // insert after already existing comments with same offset |
b31471cdc53e
7200163: add CodeComments functionality to assember stubs
kvn
parents:
6725
diff
changeset
|
1086 c->set_next(inspos->next()); |
b31471cdc53e
7200163: add CodeComments functionality to assember stubs
kvn
parents:
6725
diff
changeset
|
1087 inspos->set_next(c); |
0 | 1088 } else { |
6796
b31471cdc53e
7200163: add CodeComments functionality to assember stubs
kvn
parents:
6725
diff
changeset
|
1089 // no comments with such offset, yet. Insert before anything else. |
8767
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1090 c->set_next(_strings); |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1091 _strings = c; |
0 | 1092 } |
1093 } | |
1094 | |
8767
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1095 void CodeStrings::assign(CodeStrings& other) { |
20435 | 1096 other.check_valid(); |
1097 // Cannot do following because CodeStrings constructor is not alway run! | |
1098 assert(is_null(), "Cannot assign onto non-empty CodeStrings"); | |
8767
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1099 _strings = other._strings; |
20435 | 1100 other.set_null_and_invalidate(); |
1101 } | |
1102 | |
1103 // Deep copy of CodeStrings for consistent memory management. | |
1104 // Only used for actual disassembly so this is cheaper than reference counting | |
1105 // for the "normal" fastdebug case. | |
1106 void CodeStrings::copy(CodeStrings& other) { | |
1107 other.check_valid(); | |
1108 check_valid(); | |
1109 assert(is_null(), "Cannot copy onto non-empty CodeStrings"); | |
1110 CodeString* n = other._strings; | |
1111 CodeString** ps = &_strings; | |
1112 while (n != NULL) { | |
1113 *ps = new CodeString(n->string(),n->offset()); | |
1114 ps = &((*ps)->_next); | |
1115 n = n->next(); | |
1116 } | |
0 | 1117 } |
1118 | |
8767
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1119 void CodeStrings::print_block_comment(outputStream* stream, intptr_t offset) const { |
20435 | 1120 check_valid(); |
1121 if (_strings != NULL) { | |
8767
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1122 CodeString* c = find(offset); |
0 | 1123 while (c && c->offset() == offset) { |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
0
diff
changeset
|
1124 stream->bol(); |
0 | 1125 stream->print(" ;; "); |
17937
78bbf4d43a14
8037816: Fix for 8036122 breaks build with Xcode5/clang
drchase
parents:
17467
diff
changeset
|
1126 stream->print_cr("%s", c->string()); |
8767
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1127 c = c->next_comment(); |
0 | 1128 } |
1129 } | |
1130 } | |
1131 | |
20435 | 1132 // Also sets isNull() |
8767
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1133 void CodeStrings::free() { |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1134 CodeString* n = _strings; |
0 | 1135 while (n) { |
1136 // unlink the node from the list saving a pointer to the next | |
8767
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1137 CodeString* p = n->next(); |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1138 n->set_next(NULL); |
0 | 1139 delete n; |
1140 n = p; | |
1141 } | |
20435 | 1142 set_null_and_invalidate(); |
0 | 1143 } |
1144 | |
8767
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1145 const char* CodeStrings::add_string(const char * string) { |
20435 | 1146 check_valid(); |
8767
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1147 CodeString* s = new CodeString(string); |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1148 s->set_next(_strings); |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1149 _strings = s; |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1150 assert(s->string() != NULL, "should have a string"); |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1151 return s->string(); |
a5de0cc2f91c
8008555: Debugging code in compiled method sometimes leaks memory
roland
parents:
7409
diff
changeset
|
1152 } |
0 | 1153 |
1154 void CodeBuffer::decode() { | |
6796
b31471cdc53e
7200163: add CodeComments functionality to assember stubs
kvn
parents:
6725
diff
changeset
|
1155 ttyLocker ttyl; |
1748 | 1156 Disassembler::decode(decode_begin(), insts_end()); |
1157 _decode_begin = insts_end(); | |
0 | 1158 } |
1159 | |
1160 | |
1161 void CodeBuffer::skip_decode() { | |
1748 | 1162 _decode_begin = insts_end(); |
0 | 1163 } |
1164 | |
1165 | |
1166 void CodeBuffer::decode_all() { | |
6796
b31471cdc53e
7200163: add CodeComments functionality to assember stubs
kvn
parents:
6725
diff
changeset
|
1167 ttyLocker ttyl; |
0 | 1168 for (int n = 0; n < (int)SECT_LIMIT; n++) { |
1169 // dump contents of each section | |
1170 CodeSection* cs = code_section(n); | |
1171 tty->print_cr("! %s:", code_section_name(n)); | |
1172 if (cs != consts()) | |
1173 cs->decode(); | |
1174 else | |
1175 cs->dump(); | |
1176 } | |
1177 } | |
1178 | |
1179 | |
1180 void CodeSection::print(const char* name) { | |
1181 csize_t locs_size = locs_end() - locs_start(); | |
1182 tty->print_cr(" %7s.code = " PTR_FORMAT " : " PTR_FORMAT " : " PTR_FORMAT " (%d of %d)%s", | |
17937
78bbf4d43a14
8037816: Fix for 8036122 breaks build with Xcode5/clang
drchase
parents:
17467
diff
changeset
|
1183 name, p2i(start()), p2i(end()), p2i(limit()), size(), capacity(), |
0 | 1184 is_frozen()? " [frozen]": ""); |
1185 tty->print_cr(" %7s.locs = " PTR_FORMAT " : " PTR_FORMAT " : " PTR_FORMAT " (%d of %d) point=%d", | |
17937
78bbf4d43a14
8037816: Fix for 8036122 breaks build with Xcode5/clang
drchase
parents:
17467
diff
changeset
|
1186 name, p2i(locs_start()), p2i(locs_end()), p2i(locs_limit()), locs_size, locs_capacity(), locs_point_off()); |
0 | 1187 if (PrintRelocations) { |
1188 RelocIterator iter(this); | |
1189 iter.print(); | |
1190 } | |
1191 } | |
1192 | |
1193 void CodeBuffer::print() { | |
1194 if (this == NULL) { | |
1195 tty->print_cr("NULL CodeBuffer pointer"); | |
1196 return; | |
1197 } | |
1198 | |
1199 tty->print_cr("CodeBuffer:"); | |
1200 for (int n = 0; n < (int)SECT_LIMIT; n++) { | |
1201 // print each section | |
1202 CodeSection* cs = code_section(n); | |
1203 cs->print(code_section_name(n)); | |
1204 } | |
1205 } | |
1206 | |
1207 #endif // PRODUCT |