Mercurial > hg > truffle
annotate src/share/vm/code/relocInfo.cpp @ 1721:413ad0331a0c
6977924: Changes for 6975078 produce build error with certain gcc versions
Summary: The changes introduced for 6975078 assign badHeapOopVal to the _allocation field in the ResourceObj class. In 32 bit linux builds with certain versions of gcc this assignment will be flagged as an error while compiling allocation.cpp. In 32 bit builds the constant value badHeapOopVal (which is cast to an intptr_t) is negative. The _allocation field is typed as an unsigned intptr_t and gcc catches this as an error.
Reviewed-by: jcoomes, ysr, phh
author | johnc |
---|---|
date | Wed, 18 Aug 2010 10:59:06 -0700 |
parents | e9ff18c4ace7 |
children | 3e8fbc61cee8 |
rev | line source |
---|---|
0 | 1 /* |
1579 | 2 * Copyright (c) 1997, 2010, 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:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
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:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 # include "incls/_precompiled.incl" | |
26 # include "incls/_relocInfo.cpp.incl" | |
27 | |
28 | |
29 const RelocationHolder RelocationHolder::none; // its type is relocInfo::none | |
30 | |
31 | |
32 // Implementation of relocInfo | |
33 | |
34 #ifdef ASSERT | |
35 relocInfo::relocInfo(relocType t, int off, int f) { | |
36 assert(t != data_prefix_tag, "cannot build a prefix this way"); | |
37 assert((t & type_mask) == t, "wrong type"); | |
38 assert((f & format_mask) == f, "wrong format"); | |
39 assert(off >= 0 && off < offset_limit(), "offset out off bounds"); | |
40 assert((off & (offset_unit-1)) == 0, "misaligned offset"); | |
41 (*this) = relocInfo(t, RAW_BITS, off, f); | |
42 } | |
43 #endif | |
44 | |
45 void relocInfo::initialize(CodeSection* dest, Relocation* reloc) { | |
46 relocInfo* data = this+1; // here's where the data might go | |
47 dest->set_locs_end(data); // sync end: the next call may read dest.locs_end | |
48 reloc->pack_data_to(dest); // maybe write data into locs, advancing locs_end | |
49 relocInfo* data_limit = dest->locs_end(); | |
50 if (data_limit > data) { | |
51 relocInfo suffix = (*this); | |
52 data_limit = this->finish_prefix((short*) data_limit); | |
53 // Finish up with the suffix. (Hack note: pack_data_to might edit this.) | |
54 *data_limit = suffix; | |
55 dest->set_locs_end(data_limit+1); | |
56 } | |
57 } | |
58 | |
59 relocInfo* relocInfo::finish_prefix(short* prefix_limit) { | |
60 assert(sizeof(relocInfo) == sizeof(short), "change this code"); | |
61 short* p = (short*)(this+1); | |
62 assert(prefix_limit >= p, "must be a valid span of data"); | |
63 int plen = prefix_limit - p; | |
64 if (plen == 0) { | |
65 debug_only(_value = 0xFFFF); | |
66 return this; // no data: remove self completely | |
67 } | |
68 if (plen == 1 && fits_into_immediate(p[0])) { | |
69 (*this) = immediate_relocInfo(p[0]); // move data inside self | |
70 return this+1; | |
71 } | |
72 // cannot compact, so just update the count and return the limit pointer | |
73 (*this) = prefix_relocInfo(plen); // write new datalen | |
74 assert(data() + datalen() == prefix_limit, "pointers must line up"); | |
75 return (relocInfo*)prefix_limit; | |
76 } | |
77 | |
78 | |
79 void relocInfo::set_type(relocType t) { | |
80 int old_offset = addr_offset(); | |
81 int old_format = format(); | |
82 (*this) = relocInfo(t, old_offset, old_format); | |
83 assert(type()==(int)t, "sanity check"); | |
84 assert(addr_offset()==old_offset, "sanity check"); | |
85 assert(format()==old_format, "sanity check"); | |
86 } | |
87 | |
88 | |
89 void relocInfo::set_format(int f) { | |
90 int old_offset = addr_offset(); | |
91 assert((f & format_mask) == f, "wrong format"); | |
92 _value = (_value & ~(format_mask << offset_width)) | (f << offset_width); | |
93 assert(addr_offset()==old_offset, "sanity check"); | |
94 } | |
95 | |
96 | |
97 void relocInfo::change_reloc_info_for_address(RelocIterator *itr, address pc, relocType old_type, relocType new_type) { | |
98 bool found = false; | |
99 while (itr->next() && !found) { | |
100 if (itr->addr() == pc) { | |
101 assert(itr->type()==old_type, "wrong relocInfo type found"); | |
102 itr->current()->set_type(new_type); | |
103 found=true; | |
104 } | |
105 } | |
106 assert(found, "no relocInfo found for pc"); | |
107 } | |
108 | |
109 | |
110 void relocInfo::remove_reloc_info_for_address(RelocIterator *itr, address pc, relocType old_type) { | |
111 change_reloc_info_for_address(itr, pc, old_type, none); | |
112 } | |
113 | |
114 | |
115 // ---------------------------------------------------------------------------------------------------- | |
116 // Implementation of RelocIterator | |
117 | |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
118 void RelocIterator::initialize(nmethod* nm, address begin, address limit) { |
0 | 119 initialize_misc(); |
120 | |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
121 if (nm == NULL && begin != NULL) { |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
122 // allow nmethod to be deduced from beginning address |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
123 CodeBlob* cb = CodeCache::find_blob(begin); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
124 nm = cb->as_nmethod_or_null(); |
0 | 125 } |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
126 assert(nm != NULL, "must be able to deduce nmethod from other arguments"); |
0 | 127 |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
128 _code = nm; |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
129 _current = nm->relocation_begin() - 1; |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
130 _end = nm->relocation_end(); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
131 _addr = (address) nm->instructions_begin(); |
0 | 132 |
133 assert(!has_current(), "just checking"); | |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
134 address code_end = nm->instructions_end(); |
0 | 135 |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
136 assert(begin == NULL || begin >= nm->instructions_begin(), "in bounds"); |
0 | 137 // FIX THIS assert(limit == NULL || limit <= code_end, "in bounds"); |
138 set_limits(begin, limit); | |
139 } | |
140 | |
141 | |
142 RelocIterator::RelocIterator(CodeSection* cs, address begin, address limit) { | |
143 initialize_misc(); | |
144 | |
145 _current = cs->locs_start()-1; | |
146 _end = cs->locs_end(); | |
147 _addr = cs->start(); | |
148 _code = NULL; // Not cb->blob(); | |
149 | |
150 CodeBuffer* cb = cs->outer(); | |
151 assert((int)SECT_LIMIT == CodeBuffer::SECT_LIMIT, "my copy must be equal"); | |
152 for (int n = 0; n < (int)SECT_LIMIT; n++) { | |
153 _section_start[n] = cb->code_section(n)->start(); | |
154 } | |
155 | |
156 assert(!has_current(), "just checking"); | |
157 | |
158 assert(begin == NULL || begin >= cs->start(), "in bounds"); | |
159 assert(limit == NULL || limit <= cs->end(), "in bounds"); | |
160 set_limits(begin, limit); | |
161 } | |
162 | |
163 | |
164 enum { indexCardSize = 128 }; | |
165 struct RelocIndexEntry { | |
166 jint addr_offset; // offset from header_end of an addr() | |
167 jint reloc_offset; // offset from header_end of a relocInfo (prefix) | |
168 }; | |
169 | |
170 | |
171 static inline int num_cards(int code_size) { | |
172 return (code_size-1) / indexCardSize; | |
173 } | |
174 | |
175 | |
176 int RelocIterator::locs_and_index_size(int code_size, int locs_size) { | |
177 if (!UseRelocIndex) return locs_size; // no index | |
178 code_size = round_to(code_size, oopSize); | |
179 locs_size = round_to(locs_size, oopSize); | |
180 int index_size = num_cards(code_size) * sizeof(RelocIndexEntry); | |
181 // format of indexed relocs: | |
182 // relocation_begin: relocInfo ... | |
183 // index: (addr,reloc#) ... | |
184 // indexSize :relocation_end | |
185 return locs_size + index_size + BytesPerInt; | |
186 } | |
187 | |
188 | |
189 void RelocIterator::create_index(relocInfo* dest_begin, int dest_count, relocInfo* dest_end) { | |
190 address relocation_begin = (address)dest_begin; | |
191 address relocation_end = (address)dest_end; | |
192 int total_size = relocation_end - relocation_begin; | |
193 int locs_size = dest_count * sizeof(relocInfo); | |
194 if (!UseRelocIndex) { | |
195 Copy::fill_to_bytes(relocation_begin + locs_size, total_size-locs_size, 0); | |
196 return; | |
197 } | |
198 int index_size = total_size - locs_size - BytesPerInt; // find out how much space is left | |
199 int ncards = index_size / sizeof(RelocIndexEntry); | |
200 assert(total_size == locs_size + index_size + BytesPerInt, "checkin'"); | |
201 assert(index_size >= 0 && index_size % sizeof(RelocIndexEntry) == 0, "checkin'"); | |
202 jint* index_size_addr = (jint*)relocation_end - 1; | |
203 | |
204 assert(sizeof(jint) == BytesPerInt, "change this code"); | |
205 | |
206 *index_size_addr = index_size; | |
207 if (index_size != 0) { | |
208 assert(index_size > 0, "checkin'"); | |
209 | |
210 RelocIndexEntry* index = (RelocIndexEntry *)(relocation_begin + locs_size); | |
211 assert(index == (RelocIndexEntry*)index_size_addr - ncards, "checkin'"); | |
212 | |
213 // walk over the relocations, and fill in index entries as we go | |
214 RelocIterator iter; | |
215 const address initial_addr = NULL; | |
216 relocInfo* const initial_current = dest_begin - 1; // biased by -1 like elsewhere | |
217 | |
218 iter._code = NULL; | |
219 iter._addr = initial_addr; | |
220 iter._limit = (address)(intptr_t)(ncards * indexCardSize); | |
221 iter._current = initial_current; | |
222 iter._end = dest_begin + dest_count; | |
223 | |
224 int i = 0; | |
225 address next_card_addr = (address)indexCardSize; | |
226 int addr_offset = 0; | |
227 int reloc_offset = 0; | |
228 while (true) { | |
229 // Checkpoint the iterator before advancing it. | |
230 addr_offset = iter._addr - initial_addr; | |
231 reloc_offset = iter._current - initial_current; | |
232 if (!iter.next()) break; | |
233 while (iter.addr() >= next_card_addr) { | |
234 index[i].addr_offset = addr_offset; | |
235 index[i].reloc_offset = reloc_offset; | |
236 i++; | |
237 next_card_addr += indexCardSize; | |
238 } | |
239 } | |
240 while (i < ncards) { | |
241 index[i].addr_offset = addr_offset; | |
242 index[i].reloc_offset = reloc_offset; | |
243 i++; | |
244 } | |
245 } | |
246 } | |
247 | |
248 | |
249 void RelocIterator::set_limits(address begin, address limit) { | |
250 int index_size = 0; | |
251 if (UseRelocIndex && _code != NULL) { | |
252 index_size = ((jint*)_end)[-1]; | |
253 _end = (relocInfo*)( (address)_end - index_size - BytesPerInt ); | |
254 } | |
255 | |
256 _limit = limit; | |
257 | |
258 // the limit affects this next stuff: | |
259 if (begin != NULL) { | |
260 #ifdef ASSERT | |
261 // In ASSERT mode we do not actually use the index, but simply | |
262 // check that its contents would have led us to the right answer. | |
263 address addrCheck = _addr; | |
264 relocInfo* infoCheck = _current; | |
265 #endif // ASSERT | |
266 if (index_size > 0) { | |
267 // skip ahead | |
268 RelocIndexEntry* index = (RelocIndexEntry*)_end; | |
269 RelocIndexEntry* index_limit = (RelocIndexEntry*)((address)index + index_size); | |
270 assert(_addr == _code->instructions_begin(), "_addr must be unadjusted"); | |
271 int card = (begin - _addr) / indexCardSize; | |
272 if (card > 0) { | |
273 if (index+card-1 < index_limit) index += card-1; | |
274 else index = index_limit - 1; | |
275 #ifdef ASSERT | |
276 addrCheck = _addr + index->addr_offset; | |
277 infoCheck = _current + index->reloc_offset; | |
278 #else | |
279 // Advance the iterator immediately to the last valid state | |
280 // for the previous card. Calling "next" will then advance | |
281 // it to the first item on the required card. | |
282 _addr += index->addr_offset; | |
283 _current += index->reloc_offset; | |
284 #endif // ASSERT | |
285 } | |
286 } | |
287 | |
288 relocInfo* backup; | |
289 address backup_addr; | |
290 while (true) { | |
291 backup = _current; | |
292 backup_addr = _addr; | |
293 #ifdef ASSERT | |
294 if (backup == infoCheck) { | |
295 assert(backup_addr == addrCheck, "must match"); addrCheck = NULL; infoCheck = NULL; | |
296 } else { | |
297 assert(addrCheck == NULL || backup_addr <= addrCheck, "must not pass addrCheck"); | |
298 } | |
299 #endif // ASSERT | |
300 if (!next() || addr() >= begin) break; | |
301 } | |
302 assert(addrCheck == NULL || addrCheck == backup_addr, "must have matched addrCheck"); | |
303 assert(infoCheck == NULL || infoCheck == backup, "must have matched infoCheck"); | |
304 // At this point, either we are at the first matching record, | |
305 // or else there is no such record, and !has_current(). | |
306 // In either case, revert to the immediatly preceding state. | |
307 _current = backup; | |
308 _addr = backup_addr; | |
309 set_has_current(false); | |
310 } | |
311 } | |
312 | |
313 | |
314 void RelocIterator::set_limit(address limit) { | |
315 address code_end = (address)code() + code()->size(); | |
316 assert(limit == NULL || limit <= code_end, "in bounds"); | |
317 _limit = limit; | |
318 } | |
319 | |
320 | |
321 void PatchingRelocIterator:: prepass() { | |
322 // turn breakpoints off during patching | |
323 _init_state = (*this); // save cursor | |
324 while (next()) { | |
325 if (type() == relocInfo::breakpoint_type) { | |
326 breakpoint_reloc()->set_active(false); | |
327 } | |
328 } | |
329 (RelocIterator&)(*this) = _init_state; // reset cursor for client | |
330 } | |
331 | |
332 | |
333 void PatchingRelocIterator:: postpass() { | |
334 // turn breakpoints back on after patching | |
335 (RelocIterator&)(*this) = _init_state; // reset cursor again | |
336 while (next()) { | |
337 if (type() == relocInfo::breakpoint_type) { | |
338 breakpoint_Relocation* bpt = breakpoint_reloc(); | |
339 bpt->set_active(bpt->enabled()); | |
340 } | |
341 } | |
342 } | |
343 | |
344 | |
345 // All the strange bit-encodings are in here. | |
346 // The idea is to encode relocation data which are small integers | |
347 // very efficiently (a single extra halfword). Larger chunks of | |
348 // relocation data need a halfword header to hold their size. | |
349 void RelocIterator::advance_over_prefix() { | |
350 if (_current->is_datalen()) { | |
351 _data = (short*) _current->data(); | |
352 _datalen = _current->datalen(); | |
353 _current += _datalen + 1; // skip the embedded data & header | |
354 } else { | |
355 _databuf = _current->immediate(); | |
356 _data = &_databuf; | |
357 _datalen = 1; | |
358 _current++; // skip the header | |
359 } | |
360 // The client will see the following relocInfo, whatever that is. | |
361 // It is the reloc to which the preceding data applies. | |
362 } | |
363 | |
364 | |
365 address RelocIterator::compute_section_start(int n) const { | |
366 // This routine not only computes a section start, but also | |
367 // memoizes it for later. | |
368 #define CACHE ((RelocIterator*)this)->_section_start[n] | |
369 CodeBlob* cb = code(); | |
370 guarantee(cb != NULL, "must have a code blob"); | |
371 if (n == CodeBuffer::SECT_INSTS) | |
372 return CACHE = cb->instructions_begin(); | |
373 assert(cb->is_nmethod(), "only nmethods have these sections"); | |
374 nmethod* nm = (nmethod*) cb; | |
375 address res = NULL; | |
376 switch (n) { | |
377 case CodeBuffer::SECT_STUBS: | |
378 res = nm->stub_begin(); | |
379 break; | |
380 case CodeBuffer::SECT_CONSTS: | |
381 res = nm->consts_begin(); | |
382 break; | |
383 default: | |
384 ShouldNotReachHere(); | |
385 } | |
386 assert(nm->contains(res) || res == nm->instructions_end(), "tame pointer"); | |
387 CACHE = res; | |
388 return res; | |
389 #undef CACHE | |
390 } | |
391 | |
392 | |
393 Relocation* RelocIterator::reloc() { | |
394 // (take the "switch" out-of-line) | |
395 relocInfo::relocType t = type(); | |
396 if (false) {} | |
397 #define EACH_TYPE(name) \ | |
398 else if (t == relocInfo::name##_type) { \ | |
399 return name##_reloc(); \ | |
400 } | |
401 APPLY_TO_RELOCATIONS(EACH_TYPE); | |
402 #undef EACH_TYPE | |
403 assert(t == relocInfo::none, "must be padding"); | |
404 return new(_rh) Relocation(); | |
405 } | |
406 | |
407 | |
408 //////// Methods for flyweight Relocation types | |
409 | |
410 | |
411 RelocationHolder RelocationHolder::plus(int offset) const { | |
412 if (offset != 0) { | |
413 switch (type()) { | |
414 case relocInfo::none: | |
415 break; | |
416 case relocInfo::oop_type: | |
417 { | |
418 oop_Relocation* r = (oop_Relocation*)reloc(); | |
419 return oop_Relocation::spec(r->oop_index(), r->offset() + offset); | |
420 } | |
421 default: | |
422 ShouldNotReachHere(); | |
423 } | |
424 } | |
425 return (*this); | |
426 } | |
427 | |
428 | |
429 void Relocation::guarantee_size() { | |
430 guarantee(false, "Make _relocbuf bigger!"); | |
431 } | |
432 | |
433 // some relocations can compute their own values | |
434 address Relocation::value() { | |
435 ShouldNotReachHere(); | |
436 return NULL; | |
437 } | |
438 | |
439 | |
440 void Relocation::set_value(address x) { | |
441 ShouldNotReachHere(); | |
442 } | |
443 | |
444 | |
445 RelocationHolder Relocation::spec_simple(relocInfo::relocType rtype) { | |
446 if (rtype == relocInfo::none) return RelocationHolder::none; | |
447 relocInfo ri = relocInfo(rtype, 0); | |
448 RelocIterator itr; | |
449 itr.set_current(ri); | |
450 itr.reloc(); | |
451 return itr._rh; | |
452 } | |
453 | |
454 | |
455 static inline bool is_index(intptr_t index) { | |
456 return 0 < index && index < os::vm_page_size(); | |
457 } | |
458 | |
459 | |
460 int32_t Relocation::runtime_address_to_index(address runtime_address) { | |
461 assert(!is_index((intptr_t)runtime_address), "must not look like an index"); | |
462 | |
463 if (runtime_address == NULL) return 0; | |
464 | |
465 StubCodeDesc* p = StubCodeDesc::desc_for(runtime_address); | |
466 if (p != NULL && p->begin() == runtime_address) { | |
467 assert(is_index(p->index()), "there must not be too many stubs"); | |
468 return (int32_t)p->index(); | |
469 } else { | |
470 // Known "miscellaneous" non-stub pointers: | |
471 // os::get_polling_page(), SafepointSynchronize::address_of_state() | |
472 if (PrintRelocations) { | |
473 tty->print_cr("random unregistered address in relocInfo: " INTPTR_FORMAT, runtime_address); | |
474 } | |
475 #ifndef _LP64 | |
476 return (int32_t) (intptr_t)runtime_address; | |
477 #else | |
478 // didn't fit return non-index | |
479 return -1; | |
480 #endif /* _LP64 */ | |
481 } | |
482 } | |
483 | |
484 | |
485 address Relocation::index_to_runtime_address(int32_t index) { | |
486 if (index == 0) return NULL; | |
487 | |
488 if (is_index(index)) { | |
489 StubCodeDesc* p = StubCodeDesc::desc_for_index(index); | |
490 assert(p != NULL, "there must be a stub for this index"); | |
491 return p->begin(); | |
492 } else { | |
493 #ifndef _LP64 | |
494 // this only works on 32bit machines | |
495 return (address) ((intptr_t) index); | |
496 #else | |
497 fatal("Relocation::index_to_runtime_address, int32_t not pointer sized"); | |
498 return NULL; | |
499 #endif /* _LP64 */ | |
500 } | |
501 } | |
502 | |
503 address Relocation::old_addr_for(address newa, | |
504 const CodeBuffer* src, CodeBuffer* dest) { | |
505 int sect = dest->section_index_of(newa); | |
506 guarantee(sect != CodeBuffer::SECT_NONE, "lost track of this address"); | |
507 address ostart = src->code_section(sect)->start(); | |
508 address nstart = dest->code_section(sect)->start(); | |
509 return ostart + (newa - nstart); | |
510 } | |
511 | |
512 address Relocation::new_addr_for(address olda, | |
513 const CodeBuffer* src, CodeBuffer* dest) { | |
514 debug_only(const CodeBuffer* src0 = src); | |
515 int sect = CodeBuffer::SECT_NONE; | |
516 // Look for olda in the source buffer, and all previous incarnations | |
517 // if the source buffer has been expanded. | |
518 for (; src != NULL; src = src->before_expand()) { | |
519 sect = src->section_index_of(olda); | |
520 if (sect != CodeBuffer::SECT_NONE) break; | |
521 } | |
522 guarantee(sect != CodeBuffer::SECT_NONE, "lost track of this address"); | |
523 address ostart = src->code_section(sect)->start(); | |
524 address nstart = dest->code_section(sect)->start(); | |
525 return nstart + (olda - ostart); | |
526 } | |
527 | |
528 void Relocation::normalize_address(address& addr, const CodeSection* dest, bool allow_other_sections) { | |
529 address addr0 = addr; | |
530 if (addr0 == NULL || dest->allocates2(addr0)) return; | |
531 CodeBuffer* cb = dest->outer(); | |
532 addr = new_addr_for(addr0, cb, cb); | |
533 assert(allow_other_sections || dest->contains2(addr), | |
534 "addr must be in required section"); | |
535 } | |
536 | |
537 | |
538 void CallRelocation::set_destination(address x) { | |
539 pd_set_call_destination(x); | |
540 } | |
541 | |
542 void CallRelocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { | |
543 // Usually a self-relative reference to an external routine. | |
544 // On some platforms, the reference is absolute (not self-relative). | |
545 // The enhanced use of pd_call_destination sorts this all out. | |
546 address orig_addr = old_addr_for(addr(), src, dest); | |
547 address callee = pd_call_destination(orig_addr); | |
548 // Reassert the callee address, this time in the new copy of the code. | |
549 pd_set_call_destination(callee); | |
550 } | |
551 | |
552 | |
553 //// pack/unpack methods | |
554 | |
555 void oop_Relocation::pack_data_to(CodeSection* dest) { | |
556 short* p = (short*) dest->locs_end(); | |
557 p = pack_2_ints_to(p, _oop_index, _offset); | |
558 dest->set_locs_end((relocInfo*) p); | |
559 } | |
560 | |
561 | |
562 void oop_Relocation::unpack_data() { | |
563 unpack_2_ints(_oop_index, _offset); | |
564 } | |
565 | |
566 | |
567 void virtual_call_Relocation::pack_data_to(CodeSection* dest) { | |
568 short* p = (short*) dest->locs_end(); | |
569 address point = dest->locs_point(); | |
570 | |
571 // Try to make a pointer NULL first. | |
572 if (_oop_limit >= point && | |
573 _oop_limit <= point + NativeCall::instruction_size) { | |
574 _oop_limit = NULL; | |
575 } | |
576 // If the _oop_limit is NULL, it "defaults" to the end of the call. | |
577 // See ic_call_Relocation::oop_limit() below. | |
578 | |
579 normalize_address(_first_oop, dest); | |
580 normalize_address(_oop_limit, dest); | |
581 jint x0 = scaled_offset_null_special(_first_oop, point); | |
582 jint x1 = scaled_offset_null_special(_oop_limit, point); | |
583 p = pack_2_ints_to(p, x0, x1); | |
584 dest->set_locs_end((relocInfo*) p); | |
585 } | |
586 | |
587 | |
588 void virtual_call_Relocation::unpack_data() { | |
589 jint x0, x1; unpack_2_ints(x0, x1); | |
590 address point = addr(); | |
591 _first_oop = x0==0? NULL: address_from_scaled_offset(x0, point); | |
592 _oop_limit = x1==0? NULL: address_from_scaled_offset(x1, point); | |
593 } | |
594 | |
595 | |
596 void static_stub_Relocation::pack_data_to(CodeSection* dest) { | |
597 short* p = (short*) dest->locs_end(); | |
598 CodeSection* insts = dest->outer()->insts(); | |
599 normalize_address(_static_call, insts); | |
600 p = pack_1_int_to(p, scaled_offset(_static_call, insts->start())); | |
601 dest->set_locs_end((relocInfo*) p); | |
602 } | |
603 | |
604 void static_stub_Relocation::unpack_data() { | |
605 address base = binding()->section_start(CodeBuffer::SECT_INSTS); | |
606 _static_call = address_from_scaled_offset(unpack_1_int(), base); | |
607 } | |
608 | |
609 | |
610 void external_word_Relocation::pack_data_to(CodeSection* dest) { | |
611 short* p = (short*) dest->locs_end(); | |
612 int32_t index = runtime_address_to_index(_target); | |
613 #ifndef _LP64 | |
614 p = pack_1_int_to(p, index); | |
615 #else | |
616 if (is_index(index)) { | |
617 p = pack_2_ints_to(p, index, 0); | |
618 } else { | |
619 jlong t = (jlong) _target; | |
620 int32_t lo = low(t); | |
621 int32_t hi = high(t); | |
622 p = pack_2_ints_to(p, lo, hi); | |
623 DEBUG_ONLY(jlong t1 = jlong_from(hi, lo)); | |
624 assert(!is_index(t1) && (address) t1 == _target, "not symmetric"); | |
625 } | |
626 #endif /* _LP64 */ | |
627 dest->set_locs_end((relocInfo*) p); | |
628 } | |
629 | |
630 | |
631 void external_word_Relocation::unpack_data() { | |
632 #ifndef _LP64 | |
633 _target = index_to_runtime_address(unpack_1_int()); | |
634 #else | |
635 int32_t lo, hi; | |
636 unpack_2_ints(lo, hi); | |
637 jlong t = jlong_from(hi, lo);; | |
638 if (is_index(t)) { | |
639 _target = index_to_runtime_address(t); | |
640 } else { | |
641 _target = (address) t; | |
642 } | |
643 #endif /* _LP64 */ | |
644 } | |
645 | |
646 | |
647 void internal_word_Relocation::pack_data_to(CodeSection* dest) { | |
648 short* p = (short*) dest->locs_end(); | |
649 normalize_address(_target, dest, true); | |
650 | |
651 // Check whether my target address is valid within this section. | |
652 // If not, strengthen the relocation type to point to another section. | |
653 int sindex = _section; | |
654 if (sindex == CodeBuffer::SECT_NONE && _target != NULL | |
655 && (!dest->allocates(_target) || _target == dest->locs_point())) { | |
656 sindex = dest->outer()->section_index_of(_target); | |
657 guarantee(sindex != CodeBuffer::SECT_NONE, "must belong somewhere"); | |
658 relocInfo* base = dest->locs_end() - 1; | |
659 assert(base->type() == this->type(), "sanity"); | |
660 // Change the written type, to be section_word_type instead. | |
661 base->set_type(relocInfo::section_word_type); | |
662 } | |
663 | |
664 // Note: An internal_word relocation cannot refer to its own instruction, | |
665 // because we reserve "0" to mean that the pointer itself is embedded | |
666 // in the code stream. We use a section_word relocation for such cases. | |
667 | |
668 if (sindex == CodeBuffer::SECT_NONE) { | |
669 assert(type() == relocInfo::internal_word_type, "must be base class"); | |
670 guarantee(_target == NULL || dest->allocates2(_target), "must be within the given code section"); | |
671 jint x0 = scaled_offset_null_special(_target, dest->locs_point()); | |
672 assert(!(x0 == 0 && _target != NULL), "correct encoding of null target"); | |
673 p = pack_1_int_to(p, x0); | |
674 } else { | |
675 assert(_target != NULL, "sanity"); | |
676 CodeSection* sect = dest->outer()->code_section(sindex); | |
677 guarantee(sect->allocates2(_target), "must be in correct section"); | |
678 address base = sect->start(); | |
679 jint offset = scaled_offset(_target, base); | |
680 assert((uint)sindex < (uint)CodeBuffer::SECT_LIMIT, "sanity"); | |
681 assert(CodeBuffer::SECT_LIMIT <= (1 << section_width), "section_width++"); | |
682 p = pack_1_int_to(p, (offset << section_width) | sindex); | |
683 } | |
684 | |
685 dest->set_locs_end((relocInfo*) p); | |
686 } | |
687 | |
688 | |
689 void internal_word_Relocation::unpack_data() { | |
690 jint x0 = unpack_1_int(); | |
691 _target = x0==0? NULL: address_from_scaled_offset(x0, addr()); | |
692 _section = CodeBuffer::SECT_NONE; | |
693 } | |
694 | |
695 | |
696 void section_word_Relocation::unpack_data() { | |
697 jint x = unpack_1_int(); | |
698 jint offset = (x >> section_width); | |
699 int sindex = (x & ((1<<section_width)-1)); | |
700 address base = binding()->section_start(sindex); | |
701 | |
702 _section = sindex; | |
703 _target = address_from_scaled_offset(offset, base); | |
704 } | |
705 | |
706 | |
707 void breakpoint_Relocation::pack_data_to(CodeSection* dest) { | |
708 short* p = (short*) dest->locs_end(); | |
709 address point = dest->locs_point(); | |
710 | |
711 *p++ = _bits; | |
712 | |
713 assert(_target != NULL, "sanity"); | |
714 | |
715 if (internal()) normalize_address(_target, dest); | |
716 | |
717 jint target_bits = | |
718 (jint)( internal() ? scaled_offset (_target, point) | |
719 : runtime_address_to_index(_target) ); | |
720 if (settable()) { | |
721 // save space for set_target later | |
722 p = add_jint(p, target_bits); | |
723 } else { | |
724 p = add_var_int(p, target_bits); | |
725 } | |
726 | |
727 for (int i = 0; i < instrlen(); i++) { | |
728 // put placeholder words until bytes can be saved | |
729 p = add_short(p, (short)0x7777); | |
730 } | |
731 | |
732 dest->set_locs_end((relocInfo*) p); | |
733 } | |
734 | |
735 | |
736 void breakpoint_Relocation::unpack_data() { | |
737 _bits = live_bits(); | |
738 | |
739 int targetlen = datalen() - 1 - instrlen(); | |
740 jint target_bits = 0; | |
741 if (targetlen == 0) target_bits = 0; | |
742 else if (targetlen == 1) target_bits = *(data()+1); | |
743 else if (targetlen == 2) target_bits = relocInfo::jint_from_data(data()+1); | |
744 else { ShouldNotReachHere(); } | |
745 | |
746 _target = internal() ? address_from_scaled_offset(target_bits, addr()) | |
747 : index_to_runtime_address (target_bits); | |
748 } | |
749 | |
750 | |
751 //// miscellaneous methods | |
752 oop* oop_Relocation::oop_addr() { | |
753 int n = _oop_index; | |
754 if (n == 0) { | |
755 // oop is stored in the code stream | |
756 return (oop*) pd_address_in_code(); | |
757 } else { | |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
758 // oop is stored in table at nmethod::oops_begin |
0 | 759 return code()->oop_addr_at(n); |
760 } | |
761 } | |
762 | |
763 | |
764 oop oop_Relocation::oop_value() { | |
765 oop v = *oop_addr(); | |
766 // clean inline caches store a special pseudo-null | |
767 if (v == (oop)Universe::non_oop_word()) v = NULL; | |
768 return v; | |
769 } | |
770 | |
771 | |
772 void oop_Relocation::fix_oop_relocation() { | |
773 if (!oop_is_immediate()) { | |
774 // get the oop from the pool, and re-insert it into the instruction: | |
775 set_value(value()); | |
776 } | |
777 } | |
778 | |
779 | |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
780 RelocIterator virtual_call_Relocation::parse_ic(nmethod* &nm, address &ic_call, address &first_oop, |
0 | 781 oop* &oop_addr, bool *is_optimized) { |
782 assert(ic_call != NULL, "ic_call address must be set"); | |
783 assert(ic_call != NULL || first_oop != NULL, "must supply a non-null input"); | |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
784 if (nm == NULL) { |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
785 CodeBlob* code; |
0 | 786 if (ic_call != NULL) { |
787 code = CodeCache::find_blob(ic_call); | |
788 } else if (first_oop != NULL) { | |
789 code = CodeCache::find_blob(first_oop); | |
790 } | |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
791 nm = code->as_nmethod_or_null(); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
792 assert(nm != NULL, "address to parse must be in nmethod"); |
0 | 793 } |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
794 assert(ic_call == NULL || nm->contains(ic_call), "must be in nmethod"); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
795 assert(first_oop == NULL || nm->contains(first_oop), "must be in nmethod"); |
0 | 796 |
797 address oop_limit = NULL; | |
798 | |
799 if (ic_call != NULL) { | |
800 // search for the ic_call at the given address | |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
801 RelocIterator iter(nm, ic_call, ic_call+1); |
0 | 802 bool ret = iter.next(); |
803 assert(ret == true, "relocInfo must exist at this address"); | |
804 assert(iter.addr() == ic_call, "must find ic_call"); | |
805 if (iter.type() == relocInfo::virtual_call_type) { | |
806 virtual_call_Relocation* r = iter.virtual_call_reloc(); | |
807 first_oop = r->first_oop(); | |
808 oop_limit = r->oop_limit(); | |
809 *is_optimized = false; | |
810 } else { | |
811 assert(iter.type() == relocInfo::opt_virtual_call_type, "must be a virtual call"); | |
812 *is_optimized = true; | |
813 oop_addr = NULL; | |
814 first_oop = NULL; | |
815 return iter; | |
816 } | |
817 } | |
818 | |
819 // search for the first_oop, to get its oop_addr | |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
820 RelocIterator all_oops(nm, first_oop); |
0 | 821 RelocIterator iter = all_oops; |
822 iter.set_limit(first_oop+1); | |
823 bool found_oop = false; | |
824 while (iter.next()) { | |
825 if (iter.type() == relocInfo::oop_type) { | |
826 assert(iter.addr() == first_oop, "must find first_oop"); | |
827 oop_addr = iter.oop_reloc()->oop_addr(); | |
828 found_oop = true; | |
829 break; | |
830 } | |
831 } | |
832 assert(found_oop, "must find first_oop"); | |
833 | |
834 bool did_reset = false; | |
835 while (ic_call == NULL) { | |
836 // search forward for the ic_call matching the given first_oop | |
837 while (iter.next()) { | |
838 if (iter.type() == relocInfo::virtual_call_type) { | |
839 virtual_call_Relocation* r = iter.virtual_call_reloc(); | |
840 if (r->first_oop() == first_oop) { | |
841 ic_call = r->addr(); | |
842 oop_limit = r->oop_limit(); | |
843 break; | |
844 } | |
845 } | |
846 } | |
847 guarantee(!did_reset, "cannot find ic_call"); | |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
848 iter = RelocIterator(nm); // search the whole nmethod |
0 | 849 did_reset = true; |
850 } | |
851 | |
852 assert(oop_limit != NULL && first_oop != NULL && ic_call != NULL, ""); | |
853 all_oops.set_limit(oop_limit); | |
854 return all_oops; | |
855 } | |
856 | |
857 | |
858 address virtual_call_Relocation::first_oop() { | |
859 assert(_first_oop != NULL && _first_oop < addr(), "must precede ic_call"); | |
860 return _first_oop; | |
861 } | |
862 | |
863 | |
864 address virtual_call_Relocation::oop_limit() { | |
865 if (_oop_limit == NULL) | |
866 return addr() + NativeCall::instruction_size; | |
867 else | |
868 return _oop_limit; | |
869 } | |
870 | |
871 | |
872 | |
873 void virtual_call_Relocation::clear_inline_cache() { | |
874 // No stubs for ICs | |
875 // Clean IC | |
876 ResourceMark rm; | |
877 CompiledIC* icache = CompiledIC_at(this); | |
878 icache->set_to_clean(); | |
879 } | |
880 | |
881 | |
882 void opt_virtual_call_Relocation::clear_inline_cache() { | |
883 // No stubs for ICs | |
884 // Clean IC | |
885 ResourceMark rm; | |
886 CompiledIC* icache = CompiledIC_at(this); | |
887 icache->set_to_clean(); | |
888 } | |
889 | |
890 | |
891 address opt_virtual_call_Relocation::static_stub() { | |
892 // search for the static stub who points back to this static call | |
893 address static_call_addr = addr(); | |
894 RelocIterator iter(code()); | |
895 while (iter.next()) { | |
896 if (iter.type() == relocInfo::static_stub_type) { | |
897 if (iter.static_stub_reloc()->static_call() == static_call_addr) { | |
898 return iter.addr(); | |
899 } | |
900 } | |
901 } | |
902 return NULL; | |
903 } | |
904 | |
905 | |
906 void static_call_Relocation::clear_inline_cache() { | |
907 // Safe call site info | |
908 CompiledStaticCall* handler = compiledStaticCall_at(this); | |
909 handler->set_to_clean(); | |
910 } | |
911 | |
912 | |
913 address static_call_Relocation::static_stub() { | |
914 // search for the static stub who points back to this static call | |
915 address static_call_addr = addr(); | |
916 RelocIterator iter(code()); | |
917 while (iter.next()) { | |
918 if (iter.type() == relocInfo::static_stub_type) { | |
919 if (iter.static_stub_reloc()->static_call() == static_call_addr) { | |
920 return iter.addr(); | |
921 } | |
922 } | |
923 } | |
924 return NULL; | |
925 } | |
926 | |
927 | |
928 void static_stub_Relocation::clear_inline_cache() { | |
929 // Call stub is only used when calling the interpreted code. | |
930 // It does not really need to be cleared, except that we want to clean out the methodoop. | |
931 CompiledStaticCall::set_stub_to_clean(this); | |
932 } | |
933 | |
934 | |
935 void external_word_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { | |
936 address target = _target; | |
937 if (target == NULL) { | |
938 // An absolute embedded reference to an external location, | |
939 // which means there is nothing to fix here. | |
940 return; | |
941 } | |
942 // Probably this reference is absolute, not relative, so the | |
943 // following is probably a no-op. | |
944 assert(src->section_index_of(target) == CodeBuffer::SECT_NONE, "sanity"); | |
945 set_value(target); | |
946 } | |
947 | |
948 | |
949 address external_word_Relocation::target() { | |
950 address target = _target; | |
951 if (target == NULL) { | |
952 target = pd_get_address_from_code(); | |
953 } | |
954 return target; | |
955 } | |
956 | |
957 | |
958 void internal_word_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { | |
959 address target = _target; | |
960 if (target == NULL) { | |
961 if (addr_in_const()) { | |
962 target = new_addr_for(*(address*)addr(), src, dest); | |
963 } else { | |
964 target = new_addr_for(pd_get_address_from_code(), src, dest); | |
965 } | |
966 } | |
967 set_value(target); | |
968 } | |
969 | |
970 | |
971 address internal_word_Relocation::target() { | |
972 address target = _target; | |
973 if (target == NULL) { | |
974 target = pd_get_address_from_code(); | |
975 } | |
976 return target; | |
977 } | |
978 | |
979 | |
980 breakpoint_Relocation::breakpoint_Relocation(int kind, address target, bool internal) { | |
981 bool active = false; | |
982 bool enabled = (kind == initialization); | |
983 bool removable = (kind != safepoint); | |
984 bool settable = (target == NULL); | |
985 | |
986 int bits = kind; | |
987 if (enabled) bits |= enabled_state; | |
988 if (internal) bits |= internal_attr; | |
989 if (removable) bits |= removable_attr; | |
990 if (settable) bits |= settable_attr; | |
991 | |
992 _bits = bits | high_bit; | |
993 _target = target; | |
994 | |
995 assert(this->kind() == kind, "kind encoded"); | |
996 assert(this->enabled() == enabled, "enabled encoded"); | |
997 assert(this->active() == active, "active encoded"); | |
998 assert(this->internal() == internal, "internal encoded"); | |
999 assert(this->removable() == removable, "removable encoded"); | |
1000 assert(this->settable() == settable, "settable encoded"); | |
1001 } | |
1002 | |
1003 | |
1004 address breakpoint_Relocation::target() const { | |
1005 return _target; | |
1006 } | |
1007 | |
1008 | |
1009 void breakpoint_Relocation::set_target(address x) { | |
1010 assert(settable(), "must be settable"); | |
1011 jint target_bits = | |
1012 (jint)(internal() ? scaled_offset (x, addr()) | |
1013 : runtime_address_to_index(x)); | |
1014 short* p = &live_bits() + 1; | |
1015 p = add_jint(p, target_bits); | |
1016 assert(p == instrs(), "new target must fit"); | |
1017 _target = x; | |
1018 } | |
1019 | |
1020 | |
1021 void breakpoint_Relocation::set_enabled(bool b) { | |
1022 if (enabled() == b) return; | |
1023 | |
1024 if (b) { | |
1025 set_bits(bits() | enabled_state); | |
1026 } else { | |
1027 set_active(false); // remove the actual breakpoint insn, if any | |
1028 set_bits(bits() & ~enabled_state); | |
1029 } | |
1030 } | |
1031 | |
1032 | |
1033 void breakpoint_Relocation::set_active(bool b) { | |
1034 assert(!b || enabled(), "cannot activate a disabled breakpoint"); | |
1035 | |
1036 if (active() == b) return; | |
1037 | |
1038 // %%% should probably seize a lock here (might not be the right lock) | |
1039 //MutexLockerEx ml_patch(Patching_lock, true); | |
1040 //if (active() == b) return; // recheck state after locking | |
1041 | |
1042 if (b) { | |
1043 set_bits(bits() | active_state); | |
1044 if (instrlen() == 0) | |
1045 fatal("breakpoints in original code must be undoable"); | |
1046 pd_swap_in_breakpoint (addr(), instrs(), instrlen()); | |
1047 } else { | |
1048 set_bits(bits() & ~active_state); | |
1049 pd_swap_out_breakpoint(addr(), instrs(), instrlen()); | |
1050 } | |
1051 } | |
1052 | |
1053 | |
1054 //--------------------------------------------------------------------------------- | |
1055 // Non-product code | |
1056 | |
1057 #ifndef PRODUCT | |
1058 | |
1059 static const char* reloc_type_string(relocInfo::relocType t) { | |
1060 switch (t) { | |
1061 #define EACH_CASE(name) \ | |
1062 case relocInfo::name##_type: \ | |
1063 return #name; | |
1064 | |
1065 APPLY_TO_RELOCATIONS(EACH_CASE); | |
1066 #undef EACH_CASE | |
1067 | |
1068 case relocInfo::none: | |
1069 return "none"; | |
1070 case relocInfo::data_prefix_tag: | |
1071 return "prefix"; | |
1072 default: | |
1073 return "UNKNOWN RELOC TYPE"; | |
1074 } | |
1075 } | |
1076 | |
1077 | |
1078 void RelocIterator::print_current() { | |
1079 if (!has_current()) { | |
1080 tty->print_cr("(no relocs)"); | |
1081 return; | |
1082 } | |
1083 tty->print("relocInfo@" INTPTR_FORMAT " [type=%d(%s) addr=" INTPTR_FORMAT, | |
1084 _current, type(), reloc_type_string((relocInfo::relocType) type()), _addr); | |
1085 if (current()->format() != 0) | |
1086 tty->print(" format=%d", current()->format()); | |
1087 if (datalen() == 1) { | |
1088 tty->print(" data=%d", data()[0]); | |
1089 } else if (datalen() > 0) { | |
1090 tty->print(" data={"); | |
1091 for (int i = 0; i < datalen(); i++) { | |
1092 tty->print("%04x", data()[i] & 0xFFFF); | |
1093 } | |
1094 tty->print("}"); | |
1095 } | |
1096 tty->print("]"); | |
1097 switch (type()) { | |
1098 case relocInfo::oop_type: | |
1099 { | |
1100 oop_Relocation* r = oop_reloc(); | |
1101 oop* oop_addr = NULL; | |
1102 oop raw_oop = NULL; | |
1103 oop oop_value = NULL; | |
1104 if (code() != NULL || r->oop_is_immediate()) { | |
1105 oop_addr = r->oop_addr(); | |
1106 raw_oop = *oop_addr; | |
1107 oop_value = r->oop_value(); | |
1108 } | |
1109 tty->print(" | [oop_addr=" INTPTR_FORMAT " *=" INTPTR_FORMAT " offset=%d]", | |
1110 oop_addr, (address)raw_oop, r->offset()); | |
1111 // Do not print the oop by default--we want this routine to | |
1112 // work even during GC or other inconvenient times. | |
1113 if (WizardMode && oop_value != NULL) { | |
1114 tty->print("oop_value=" INTPTR_FORMAT ": ", (address)oop_value); | |
1115 oop_value->print_value_on(tty); | |
1116 } | |
1117 break; | |
1118 } | |
1119 case relocInfo::external_word_type: | |
1120 case relocInfo::internal_word_type: | |
1121 case relocInfo::section_word_type: | |
1122 { | |
1123 DataRelocation* r = (DataRelocation*) reloc(); | |
1124 tty->print(" | [target=" INTPTR_FORMAT "]", r->value()); //value==target | |
1125 break; | |
1126 } | |
1127 case relocInfo::static_call_type: | |
1128 case relocInfo::runtime_call_type: | |
1129 { | |
1130 CallRelocation* r = (CallRelocation*) reloc(); | |
1131 tty->print(" | [destination=" INTPTR_FORMAT "]", r->destination()); | |
1132 break; | |
1133 } | |
1134 case relocInfo::virtual_call_type: | |
1135 { | |
1136 virtual_call_Relocation* r = (virtual_call_Relocation*) reloc(); | |
1137 tty->print(" | [destination=" INTPTR_FORMAT " first_oop=" INTPTR_FORMAT " oop_limit=" INTPTR_FORMAT "]", | |
1138 r->destination(), r->first_oop(), r->oop_limit()); | |
1139 break; | |
1140 } | |
1141 case relocInfo::static_stub_type: | |
1142 { | |
1143 static_stub_Relocation* r = (static_stub_Relocation*) reloc(); | |
1144 tty->print(" | [static_call=" INTPTR_FORMAT "]", r->static_call()); | |
1145 break; | |
1146 } | |
1147 } | |
1148 tty->cr(); | |
1149 } | |
1150 | |
1151 | |
1152 void RelocIterator::print() { | |
1153 RelocIterator save_this = (*this); | |
1154 relocInfo* scan = _current; | |
1155 if (!has_current()) scan += 1; // nothing to scan here! | |
1156 | |
1157 bool skip_next = has_current(); | |
1158 bool got_next; | |
1159 while (true) { | |
1160 got_next = (skip_next || next()); | |
1161 skip_next = false; | |
1162 | |
1163 tty->print(" @" INTPTR_FORMAT ": ", scan); | |
1164 relocInfo* newscan = _current+1; | |
1165 if (!has_current()) newscan -= 1; // nothing to scan here! | |
1166 while (scan < newscan) { | |
1167 tty->print("%04x", *(short*)scan & 0xFFFF); | |
1168 scan++; | |
1169 } | |
1170 tty->cr(); | |
1171 | |
1172 if (!got_next) break; | |
1173 print_current(); | |
1174 } | |
1175 | |
1176 (*this) = save_this; | |
1177 } | |
1178 | |
1179 // For the debugger: | |
1180 extern "C" | |
1563
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
1181 void print_blob_locs(nmethod* nm) { |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
1182 nm->print(); |
1a5913bf5e19
6951083: oops and relocations should part of nmethod not CodeBlob
twisti
parents:
0
diff
changeset
|
1183 RelocIterator iter(nm); |
0 | 1184 iter.print(); |
1185 } | |
1186 extern "C" | |
1187 void print_buf_locs(CodeBuffer* cb) { | |
1188 FlagSetting fs(PrintRelocations, true); | |
1189 cb->print(); | |
1190 } | |
1191 #endif // !PRODUCT |