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