1 | /* |
2 | * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. |
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | * |
5 | * This code is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 only, as |
7 | * published by the Free Software Foundation. |
8 | * |
9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
12 | * version 2 for more details (a copy is included in the LICENSE file that |
13 | * accompanied this code). |
14 | * |
15 | * You should have received a copy of the GNU General Public License version |
16 | * 2 along with this work; if not, write to the Free Software Foundation, |
17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
18 | * |
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 | * or visit www.oracle.com if you need additional information or have any |
21 | * questions. |
22 | * |
23 | */ |
24 | |
25 | #include "precompiled.hpp" |
26 | #include "code/codeCache.hpp" |
27 | #include "code/compiledIC.hpp" |
28 | #include "code/nmethod.hpp" |
29 | #include "code/relocInfo.hpp" |
30 | #include "memory/resourceArea.hpp" |
31 | #include "memory/universe.hpp" |
32 | #include "oops/compressedOops.inline.hpp" |
33 | #include "runtime/flags/flagSetting.hpp" |
34 | #include "runtime/stubCodeGenerator.hpp" |
35 | #include "utilities/copy.hpp" |
36 | #include "oops/oop.inline.hpp" |
37 | |
38 | const RelocationHolder RelocationHolder::none; // its type is relocInfo::none |
39 | |
40 | |
41 | // Implementation of relocInfo |
42 | |
43 | #ifdef ASSERT |
44 | relocInfo::relocInfo(relocType t, int off, int f) { |
45 | assert(t != data_prefix_tag, "cannot build a prefix this way" ); |
46 | assert((t & type_mask) == t, "wrong type" ); |
47 | assert((f & format_mask) == f, "wrong format" ); |
48 | assert(off >= 0 && off < offset_limit(), "offset out off bounds" ); |
49 | assert((off & (offset_unit-1)) == 0, "misaligned offset" ); |
50 | (*this) = relocInfo(t, RAW_BITS, off, f); |
51 | } |
52 | #endif |
53 | |
54 | void relocInfo::initialize(CodeSection* dest, Relocation* reloc) { |
55 | relocInfo* data = this+1; // here's where the data might go |
56 | dest->set_locs_end(data); // sync end: the next call may read dest.locs_end |
57 | reloc->pack_data_to(dest); // maybe write data into locs, advancing locs_end |
58 | relocInfo* data_limit = dest->locs_end(); |
59 | if (data_limit > data) { |
60 | relocInfo suffix = (*this); |
61 | data_limit = this->finish_prefix((short*) data_limit); |
62 | // Finish up with the suffix. (Hack note: pack_data_to might edit this.) |
63 | *data_limit = suffix; |
64 | dest->set_locs_end(data_limit+1); |
65 | } |
66 | } |
67 | |
68 | relocInfo* relocInfo::finish_prefix(short* prefix_limit) { |
69 | assert(sizeof(relocInfo) == sizeof(short), "change this code" ); |
70 | short* p = (short*)(this+1); |
71 | assert(prefix_limit >= p, "must be a valid span of data" ); |
72 | int plen = prefix_limit - p; |
73 | if (plen == 0) { |
74 | debug_only(_value = 0xFFFF); |
75 | return this; // no data: remove self completely |
76 | } |
77 | if (plen == 1 && fits_into_immediate(p[0])) { |
78 | (*this) = immediate_relocInfo(p[0]); // move data inside self |
79 | return this+1; |
80 | } |
81 | // cannot compact, so just update the count and return the limit pointer |
82 | (*this) = prefix_relocInfo(plen); // write new datalen |
83 | assert(data() + datalen() == prefix_limit, "pointers must line up" ); |
84 | return (relocInfo*)prefix_limit; |
85 | } |
86 | |
87 | void relocInfo::set_type(relocType t) { |
88 | int old_offset = addr_offset(); |
89 | int old_format = format(); |
90 | (*this) = relocInfo(t, old_offset, old_format); |
91 | assert(type()==(int)t, "sanity check" ); |
92 | assert(addr_offset()==old_offset, "sanity check" ); |
93 | assert(format()==old_format, "sanity check" ); |
94 | } |
95 | |
96 | void relocInfo::change_reloc_info_for_address(RelocIterator *itr, address pc, relocType old_type, relocType new_type) { |
97 | bool found = false; |
98 | while (itr->next() && !found) { |
99 | if (itr->addr() == pc) { |
100 | assert(itr->type()==old_type, "wrong relocInfo type found" ); |
101 | itr->current()->set_type(new_type); |
102 | found=true; |
103 | } |
104 | } |
105 | assert(found, "no relocInfo found for pc" ); |
106 | } |
107 | |
108 | |
109 | // ---------------------------------------------------------------------------------------------------- |
110 | // Implementation of RelocIterator |
111 | |
112 | void RelocIterator::initialize(CompiledMethod* nm, address begin, address limit) { |
113 | initialize_misc(); |
114 | |
115 | if (nm == NULL && begin != NULL) { |
116 | // allow nmethod to be deduced from beginning address |
117 | CodeBlob* cb = CodeCache::find_blob(begin); |
118 | nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL; |
119 | } |
120 | guarantee(nm != NULL, "must be able to deduce nmethod from other arguments" ); |
121 | |
122 | _code = nm; |
123 | _current = nm->relocation_begin() - 1; |
124 | _end = nm->relocation_end(); |
125 | _addr = nm->content_begin(); |
126 | |
127 | // Initialize code sections. |
128 | _section_start[CodeBuffer::SECT_CONSTS] = nm->consts_begin(); |
129 | _section_start[CodeBuffer::SECT_INSTS ] = nm->insts_begin() ; |
130 | _section_start[CodeBuffer::SECT_STUBS ] = nm->stub_begin() ; |
131 | |
132 | _section_end [CodeBuffer::SECT_CONSTS] = nm->consts_end() ; |
133 | _section_end [CodeBuffer::SECT_INSTS ] = nm->insts_end() ; |
134 | _section_end [CodeBuffer::SECT_STUBS ] = nm->stub_end() ; |
135 | |
136 | assert(!has_current(), "just checking" ); |
137 | assert(begin == NULL || begin >= nm->code_begin(), "in bounds" ); |
138 | assert(limit == NULL || limit <= nm->code_end(), "in bounds" ); |
139 | set_limits(begin, limit); |
140 | } |
141 | |
142 | |
143 | RelocIterator::RelocIterator(CodeSection* cs, address begin, address limit) { |
144 | initialize_misc(); |
145 | |
146 | _current = cs->locs_start()-1; |
147 | _end = cs->locs_end(); |
148 | _addr = cs->start(); |
149 | _code = NULL; // Not cb->blob(); |
150 | |
151 | CodeBuffer* cb = cs->outer(); |
152 | assert((int) SECT_LIMIT == CodeBuffer::SECT_LIMIT, "my copy must be equal" ); |
153 | for (int n = (int) CodeBuffer::SECT_FIRST; n < (int) CodeBuffer::SECT_LIMIT; n++) { |
154 | CodeSection* cs = cb->code_section(n); |
155 | _section_start[n] = cs->start(); |
156 | _section_end [n] = cs->end(); |
157 | } |
158 | |
159 | assert(!has_current(), "just checking" ); |
160 | |
161 | assert(begin == NULL || begin >= cs->start(), "in bounds" ); |
162 | assert(limit == NULL || limit <= cs->end(), "in bounds" ); |
163 | set_limits(begin, limit); |
164 | } |
165 | |
166 | bool RelocIterator::addr_in_const() const { |
167 | const int n = CodeBuffer::SECT_CONSTS; |
168 | return section_start(n) <= addr() && addr() < section_end(n); |
169 | } |
170 | |
171 | |
172 | void RelocIterator::set_limits(address begin, address limit) { |
173 | _limit = limit; |
174 | |
175 | // the limit affects this next stuff: |
176 | if (begin != NULL) { |
177 | relocInfo* backup; |
178 | address backup_addr; |
179 | while (true) { |
180 | backup = _current; |
181 | backup_addr = _addr; |
182 | if (!next() || addr() >= begin) break; |
183 | } |
184 | // At this point, either we are at the first matching record, |
185 | // or else there is no such record, and !has_current(). |
186 | // In either case, revert to the immediatly preceding state. |
187 | _current = backup; |
188 | _addr = backup_addr; |
189 | set_has_current(false); |
190 | } |
191 | } |
192 | |
193 | |
194 | // All the strange bit-encodings are in here. |
195 | // The idea is to encode relocation data which are small integers |
196 | // very efficiently (a single extra halfword). Larger chunks of |
197 | // relocation data need a halfword header to hold their size. |
198 | void RelocIterator::advance_over_prefix() { |
199 | if (_current->is_datalen()) { |
200 | _data = (short*) _current->data(); |
201 | _datalen = _current->datalen(); |
202 | _current += _datalen + 1; // skip the embedded data & header |
203 | } else { |
204 | _databuf = _current->immediate(); |
205 | _data = &_databuf; |
206 | _datalen = 1; |
207 | _current++; // skip the header |
208 | } |
209 | // The client will see the following relocInfo, whatever that is. |
210 | // It is the reloc to which the preceding data applies. |
211 | } |
212 | |
213 | |
214 | void RelocIterator::initialize_misc() { |
215 | set_has_current(false); |
216 | for (int i = (int) CodeBuffer::SECT_FIRST; i < (int) CodeBuffer::SECT_LIMIT; i++) { |
217 | _section_start[i] = NULL; // these will be lazily computed, if needed |
218 | _section_end [i] = NULL; |
219 | } |
220 | } |
221 | |
222 | |
223 | Relocation* RelocIterator::reloc() { |
224 | // (take the "switch" out-of-line) |
225 | relocInfo::relocType t = type(); |
226 | if (false) {} |
227 | #define EACH_TYPE(name) \ |
228 | else if (t == relocInfo::name##_type) { \ |
229 | return name##_reloc(); \ |
230 | } |
231 | APPLY_TO_RELOCATIONS(EACH_TYPE); |
232 | #undef EACH_TYPE |
233 | assert(t == relocInfo::none, "must be padding" ); |
234 | return new(_rh) Relocation(); |
235 | } |
236 | |
237 | |
238 | //////// Methods for flyweight Relocation types |
239 | |
240 | |
241 | RelocationHolder RelocationHolder::plus(int offset) const { |
242 | if (offset != 0) { |
243 | switch (type()) { |
244 | case relocInfo::none: |
245 | break; |
246 | case relocInfo::oop_type: |
247 | { |
248 | oop_Relocation* r = (oop_Relocation*)reloc(); |
249 | return oop_Relocation::spec(r->oop_index(), r->offset() + offset); |
250 | } |
251 | case relocInfo::metadata_type: |
252 | { |
253 | metadata_Relocation* r = (metadata_Relocation*)reloc(); |
254 | return metadata_Relocation::spec(r->metadata_index(), r->offset() + offset); |
255 | } |
256 | default: |
257 | ShouldNotReachHere(); |
258 | } |
259 | } |
260 | return (*this); |
261 | } |
262 | |
263 | |
264 | void Relocation::guarantee_size() { |
265 | guarantee(false, "Make _relocbuf bigger!" ); |
266 | } |
267 | |
268 | // some relocations can compute their own values |
269 | address Relocation::value() { |
270 | ShouldNotReachHere(); |
271 | return NULL; |
272 | } |
273 | |
274 | |
275 | void Relocation::set_value(address x) { |
276 | ShouldNotReachHere(); |
277 | } |
278 | |
279 | void Relocation::const_set_data_value(address x) { |
280 | #ifdef _LP64 |
281 | if (format() == relocInfo::narrow_oop_in_const) { |
282 | *(narrowOop*)addr() = CompressedOops::encode((oop) x); |
283 | } else { |
284 | #endif |
285 | *(address*)addr() = x; |
286 | #ifdef _LP64 |
287 | } |
288 | #endif |
289 | } |
290 | |
291 | void Relocation::const_verify_data_value(address x) { |
292 | #ifdef _LP64 |
293 | if (format() == relocInfo::narrow_oop_in_const) { |
294 | guarantee(*(narrowOop*)addr() == CompressedOops::encode((oop) x), "must agree" ); |
295 | } else { |
296 | #endif |
297 | guarantee(*(address*)addr() == x, "must agree" ); |
298 | #ifdef _LP64 |
299 | } |
300 | #endif |
301 | } |
302 | |
303 | |
304 | RelocationHolder Relocation::spec_simple(relocInfo::relocType rtype) { |
305 | if (rtype == relocInfo::none) return RelocationHolder::none; |
306 | relocInfo ri = relocInfo(rtype, 0); |
307 | RelocIterator itr; |
308 | itr.set_current(ri); |
309 | itr.reloc(); |
310 | return itr._rh; |
311 | } |
312 | |
313 | address Relocation::old_addr_for(address newa, |
314 | const CodeBuffer* src, CodeBuffer* dest) { |
315 | int sect = dest->section_index_of(newa); |
316 | guarantee(sect != CodeBuffer::SECT_NONE, "lost track of this address" ); |
317 | address ostart = src->code_section(sect)->start(); |
318 | address nstart = dest->code_section(sect)->start(); |
319 | return ostart + (newa - nstart); |
320 | } |
321 | |
322 | address Relocation::new_addr_for(address olda, |
323 | const CodeBuffer* src, CodeBuffer* dest) { |
324 | debug_only(const CodeBuffer* src0 = src); |
325 | int sect = CodeBuffer::SECT_NONE; |
326 | // Look for olda in the source buffer, and all previous incarnations |
327 | // if the source buffer has been expanded. |
328 | for (; src != NULL; src = src->before_expand()) { |
329 | sect = src->section_index_of(olda); |
330 | if (sect != CodeBuffer::SECT_NONE) break; |
331 | } |
332 | guarantee(sect != CodeBuffer::SECT_NONE, "lost track of this address" ); |
333 | address ostart = src->code_section(sect)->start(); |
334 | address nstart = dest->code_section(sect)->start(); |
335 | return nstart + (olda - ostart); |
336 | } |
337 | |
338 | void Relocation::normalize_address(address& addr, const CodeSection* dest, bool allow_other_sections) { |
339 | address addr0 = addr; |
340 | if (addr0 == NULL || dest->allocates2(addr0)) return; |
341 | CodeBuffer* cb = dest->outer(); |
342 | addr = new_addr_for(addr0, cb, cb); |
343 | assert(allow_other_sections || dest->contains2(addr), |
344 | "addr must be in required section" ); |
345 | } |
346 | |
347 | |
348 | void CallRelocation::set_destination(address x) { |
349 | pd_set_call_destination(x); |
350 | } |
351 | |
352 | void CallRelocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { |
353 | // Usually a self-relative reference to an external routine. |
354 | // On some platforms, the reference is absolute (not self-relative). |
355 | // The enhanced use of pd_call_destination sorts this all out. |
356 | address orig_addr = old_addr_for(addr(), src, dest); |
357 | address callee = pd_call_destination(orig_addr); |
358 | // Reassert the callee address, this time in the new copy of the code. |
359 | pd_set_call_destination(callee); |
360 | } |
361 | |
362 | |
363 | //// pack/unpack methods |
364 | |
365 | void oop_Relocation::pack_data_to(CodeSection* dest) { |
366 | short* p = (short*) dest->locs_end(); |
367 | p = pack_2_ints_to(p, _oop_index, _offset); |
368 | dest->set_locs_end((relocInfo*) p); |
369 | } |
370 | |
371 | |
372 | void oop_Relocation::unpack_data() { |
373 | unpack_2_ints(_oop_index, _offset); |
374 | } |
375 | |
376 | void metadata_Relocation::pack_data_to(CodeSection* dest) { |
377 | short* p = (short*) dest->locs_end(); |
378 | p = pack_2_ints_to(p, _metadata_index, _offset); |
379 | dest->set_locs_end((relocInfo*) p); |
380 | } |
381 | |
382 | |
383 | void metadata_Relocation::unpack_data() { |
384 | unpack_2_ints(_metadata_index, _offset); |
385 | } |
386 | |
387 | |
388 | void virtual_call_Relocation::pack_data_to(CodeSection* dest) { |
389 | short* p = (short*) dest->locs_end(); |
390 | address point = dest->locs_point(); |
391 | |
392 | normalize_address(_cached_value, dest); |
393 | jint x0 = scaled_offset_null_special(_cached_value, point); |
394 | p = pack_2_ints_to(p, x0, _method_index); |
395 | dest->set_locs_end((relocInfo*) p); |
396 | } |
397 | |
398 | |
399 | void virtual_call_Relocation::unpack_data() { |
400 | jint x0 = 0; |
401 | unpack_2_ints(x0, _method_index); |
402 | address point = addr(); |
403 | _cached_value = x0==0? NULL: address_from_scaled_offset(x0, point); |
404 | } |
405 | |
406 | void runtime_call_w_cp_Relocation::pack_data_to(CodeSection * dest) { |
407 | short* p = pack_1_int_to((short *)dest->locs_end(), (jint)(_offset >> 2)); |
408 | dest->set_locs_end((relocInfo*) p); |
409 | } |
410 | |
411 | void runtime_call_w_cp_Relocation::unpack_data() { |
412 | _offset = unpack_1_int() << 2; |
413 | } |
414 | |
415 | void static_stub_Relocation::pack_data_to(CodeSection* dest) { |
416 | short* p = (short*) dest->locs_end(); |
417 | CodeSection* insts = dest->outer()->insts(); |
418 | normalize_address(_static_call, insts); |
419 | jint is_aot = _is_aot ? 1 : 0; |
420 | p = pack_2_ints_to(p, scaled_offset(_static_call, insts->start()), is_aot); |
421 | dest->set_locs_end((relocInfo*) p); |
422 | } |
423 | |
424 | void static_stub_Relocation::unpack_data() { |
425 | address base = binding()->section_start(CodeBuffer::SECT_INSTS); |
426 | jint offset; |
427 | jint is_aot; |
428 | unpack_2_ints(offset, is_aot); |
429 | _static_call = address_from_scaled_offset(offset, base); |
430 | _is_aot = (is_aot == 1); |
431 | } |
432 | |
433 | void trampoline_stub_Relocation::pack_data_to(CodeSection* dest ) { |
434 | short* p = (short*) dest->locs_end(); |
435 | CodeSection* insts = dest->outer()->insts(); |
436 | normalize_address(_owner, insts); |
437 | p = pack_1_int_to(p, scaled_offset(_owner, insts->start())); |
438 | dest->set_locs_end((relocInfo*) p); |
439 | } |
440 | |
441 | void trampoline_stub_Relocation::unpack_data() { |
442 | address base = binding()->section_start(CodeBuffer::SECT_INSTS); |
443 | _owner = address_from_scaled_offset(unpack_1_int(), base); |
444 | } |
445 | |
446 | void external_word_Relocation::pack_data_to(CodeSection* dest) { |
447 | short* p = (short*) dest->locs_end(); |
448 | #ifndef _LP64 |
449 | p = pack_1_int_to(p, (int32_t) (intptr_t)_target); |
450 | #else |
451 | jlong t = (jlong) _target; |
452 | int32_t lo = low(t); |
453 | int32_t hi = high(t); |
454 | p = pack_2_ints_to(p, lo, hi); |
455 | #endif /* _LP64 */ |
456 | dest->set_locs_end((relocInfo*) p); |
457 | } |
458 | |
459 | |
460 | void external_word_Relocation::unpack_data() { |
461 | #ifndef _LP64 |
462 | _target = (address) (intptr_t)unpack_1_int(); |
463 | #else |
464 | jint lo, hi; |
465 | unpack_2_ints(lo, hi); |
466 | jlong t = jlong_from(hi, lo);; |
467 | _target = (address) t; |
468 | #endif /* _LP64 */ |
469 | } |
470 | |
471 | |
472 | void internal_word_Relocation::pack_data_to(CodeSection* dest) { |
473 | short* p = (short*) dest->locs_end(); |
474 | normalize_address(_target, dest, true); |
475 | |
476 | // Check whether my target address is valid within this section. |
477 | // If not, strengthen the relocation type to point to another section. |
478 | int sindex = _section; |
479 | if (sindex == CodeBuffer::SECT_NONE && _target != NULL |
480 | && (!dest->allocates(_target) || _target == dest->locs_point())) { |
481 | sindex = dest->outer()->section_index_of(_target); |
482 | guarantee(sindex != CodeBuffer::SECT_NONE, "must belong somewhere" ); |
483 | relocInfo* base = dest->locs_end() - 1; |
484 | assert(base->type() == this->type(), "sanity" ); |
485 | // Change the written type, to be section_word_type instead. |
486 | base->set_type(relocInfo::section_word_type); |
487 | } |
488 | |
489 | // Note: An internal_word relocation cannot refer to its own instruction, |
490 | // because we reserve "0" to mean that the pointer itself is embedded |
491 | // in the code stream. We use a section_word relocation for such cases. |
492 | |
493 | if (sindex == CodeBuffer::SECT_NONE) { |
494 | assert(type() == relocInfo::internal_word_type, "must be base class" ); |
495 | guarantee(_target == NULL || dest->allocates2(_target), "must be within the given code section" ); |
496 | jint x0 = scaled_offset_null_special(_target, dest->locs_point()); |
497 | assert(!(x0 == 0 && _target != NULL), "correct encoding of null target" ); |
498 | p = pack_1_int_to(p, x0); |
499 | } else { |
500 | assert(_target != NULL, "sanity" ); |
501 | CodeSection* sect = dest->outer()->code_section(sindex); |
502 | guarantee(sect->allocates2(_target), "must be in correct section" ); |
503 | address base = sect->start(); |
504 | jint offset = scaled_offset(_target, base); |
505 | assert((uint)sindex < (uint)CodeBuffer::SECT_LIMIT, "sanity" ); |
506 | assert(CodeBuffer::SECT_LIMIT <= (1 << section_width), "section_width++" ); |
507 | p = pack_1_int_to(p, (offset << section_width) | sindex); |
508 | } |
509 | |
510 | dest->set_locs_end((relocInfo*) p); |
511 | } |
512 | |
513 | |
514 | void internal_word_Relocation::unpack_data() { |
515 | jint x0 = unpack_1_int(); |
516 | _target = x0==0? NULL: address_from_scaled_offset(x0, addr()); |
517 | _section = CodeBuffer::SECT_NONE; |
518 | } |
519 | |
520 | |
521 | void section_word_Relocation::unpack_data() { |
522 | jint x = unpack_1_int(); |
523 | jint offset = (x >> section_width); |
524 | int sindex = (x & ((1<<section_width)-1)); |
525 | address base = binding()->section_start(sindex); |
526 | |
527 | _section = sindex; |
528 | _target = address_from_scaled_offset(offset, base); |
529 | } |
530 | |
531 | //// miscellaneous methods |
532 | oop* oop_Relocation::oop_addr() { |
533 | int n = _oop_index; |
534 | if (n == 0) { |
535 | // oop is stored in the code stream |
536 | return (oop*) pd_address_in_code(); |
537 | } else { |
538 | // oop is stored in table at nmethod::oops_begin |
539 | return code()->oop_addr_at(n); |
540 | } |
541 | } |
542 | |
543 | |
544 | oop oop_Relocation::oop_value() { |
545 | oop v = *oop_addr(); |
546 | // clean inline caches store a special pseudo-null |
547 | if (v == Universe::non_oop_word()) v = NULL; |
548 | return v; |
549 | } |
550 | |
551 | |
552 | void oop_Relocation::fix_oop_relocation() { |
553 | if (!oop_is_immediate()) { |
554 | // get the oop from the pool, and re-insert it into the instruction: |
555 | set_value(value()); |
556 | } |
557 | } |
558 | |
559 | |
560 | void oop_Relocation::verify_oop_relocation() { |
561 | if (!oop_is_immediate()) { |
562 | // get the oop from the pool, and re-insert it into the instruction: |
563 | verify_value(value()); |
564 | } |
565 | } |
566 | |
567 | // meta data versions |
568 | Metadata** metadata_Relocation::metadata_addr() { |
569 | int n = _metadata_index; |
570 | if (n == 0) { |
571 | // metadata is stored in the code stream |
572 | return (Metadata**) pd_address_in_code(); |
573 | } else { |
574 | // metadata is stored in table at nmethod::metadatas_begin |
575 | return code()->metadata_addr_at(n); |
576 | } |
577 | } |
578 | |
579 | |
580 | Metadata* metadata_Relocation::metadata_value() { |
581 | Metadata* v = *metadata_addr(); |
582 | // clean inline caches store a special pseudo-null |
583 | if (v == (Metadata*)Universe::non_oop_word()) v = NULL; |
584 | return v; |
585 | } |
586 | |
587 | |
588 | void metadata_Relocation::fix_metadata_relocation() { |
589 | if (!metadata_is_immediate()) { |
590 | // get the metadata from the pool, and re-insert it into the instruction: |
591 | pd_fix_value(value()); |
592 | } |
593 | } |
594 | |
595 | address virtual_call_Relocation::cached_value() { |
596 | assert(_cached_value != NULL && _cached_value < addr(), "must precede ic_call" ); |
597 | return _cached_value; |
598 | } |
599 | |
600 | Method* virtual_call_Relocation::method_value() { |
601 | CompiledMethod* cm = code(); |
602 | if (cm == NULL) return (Method*)NULL; |
603 | Metadata* m = cm->metadata_at(_method_index); |
604 | assert(m != NULL || _method_index == 0, "should be non-null for non-zero index" ); |
605 | assert(m == NULL || m->is_method(), "not a method" ); |
606 | return (Method*)m; |
607 | } |
608 | |
609 | bool virtual_call_Relocation::clear_inline_cache() { |
610 | // No stubs for ICs |
611 | // Clean IC |
612 | ResourceMark rm; |
613 | CompiledIC* icache = CompiledIC_at(this); |
614 | return icache->set_to_clean(); |
615 | } |
616 | |
617 | |
618 | void opt_virtual_call_Relocation::pack_data_to(CodeSection* dest) { |
619 | short* p = (short*) dest->locs_end(); |
620 | p = pack_1_int_to(p, _method_index); |
621 | dest->set_locs_end((relocInfo*) p); |
622 | } |
623 | |
624 | void opt_virtual_call_Relocation::unpack_data() { |
625 | _method_index = unpack_1_int(); |
626 | } |
627 | |
628 | Method* opt_virtual_call_Relocation::method_value() { |
629 | CompiledMethod* cm = code(); |
630 | if (cm == NULL) return (Method*)NULL; |
631 | Metadata* m = cm->metadata_at(_method_index); |
632 | assert(m != NULL || _method_index == 0, "should be non-null for non-zero index" ); |
633 | assert(m == NULL || m->is_method(), "not a method" ); |
634 | return (Method*)m; |
635 | } |
636 | |
637 | template<typename CompiledICorStaticCall> |
638 | static bool set_to_clean_no_ic_refill(CompiledICorStaticCall* ic) { |
639 | guarantee(ic->set_to_clean(), "Should not need transition stubs" ); |
640 | return true; |
641 | } |
642 | |
643 | bool opt_virtual_call_Relocation::clear_inline_cache() { |
644 | // No stubs for ICs |
645 | // Clean IC |
646 | ResourceMark rm; |
647 | CompiledIC* icache = CompiledIC_at(this); |
648 | return set_to_clean_no_ic_refill(icache); |
649 | } |
650 | |
651 | address opt_virtual_call_Relocation::static_stub(bool is_aot) { |
652 | // search for the static stub who points back to this static call |
653 | address static_call_addr = addr(); |
654 | RelocIterator iter(code()); |
655 | while (iter.next()) { |
656 | if (iter.type() == relocInfo::static_stub_type) { |
657 | static_stub_Relocation* stub_reloc = iter.static_stub_reloc(); |
658 | if (stub_reloc->static_call() == static_call_addr && stub_reloc->is_aot() == is_aot) { |
659 | return iter.addr(); |
660 | } |
661 | } |
662 | } |
663 | return NULL; |
664 | } |
665 | |
666 | Method* static_call_Relocation::method_value() { |
667 | CompiledMethod* cm = code(); |
668 | if (cm == NULL) return (Method*)NULL; |
669 | Metadata* m = cm->metadata_at(_method_index); |
670 | assert(m != NULL || _method_index == 0, "should be non-null for non-zero index" ); |
671 | assert(m == NULL || m->is_method(), "not a method" ); |
672 | return (Method*)m; |
673 | } |
674 | |
675 | void static_call_Relocation::pack_data_to(CodeSection* dest) { |
676 | short* p = (short*) dest->locs_end(); |
677 | p = pack_1_int_to(p, _method_index); |
678 | dest->set_locs_end((relocInfo*) p); |
679 | } |
680 | |
681 | void static_call_Relocation::unpack_data() { |
682 | _method_index = unpack_1_int(); |
683 | } |
684 | |
685 | bool static_call_Relocation::clear_inline_cache() { |
686 | // Safe call site info |
687 | CompiledStaticCall* handler = this->code()->compiledStaticCall_at(this); |
688 | return set_to_clean_no_ic_refill(handler); |
689 | } |
690 | |
691 | |
692 | address static_call_Relocation::static_stub(bool is_aot) { |
693 | // search for the static stub who points back to this static call |
694 | address static_call_addr = addr(); |
695 | RelocIterator iter(code()); |
696 | while (iter.next()) { |
697 | if (iter.type() == relocInfo::static_stub_type) { |
698 | static_stub_Relocation* stub_reloc = iter.static_stub_reloc(); |
699 | if (stub_reloc->static_call() == static_call_addr && stub_reloc->is_aot() == is_aot) { |
700 | return iter.addr(); |
701 | } |
702 | } |
703 | } |
704 | return NULL; |
705 | } |
706 | |
707 | // Finds the trampoline address for a call. If no trampoline stub is |
708 | // found NULL is returned which can be handled by the caller. |
709 | address trampoline_stub_Relocation::get_trampoline_for(address call, nmethod* code) { |
710 | // There are no relocations available when the code gets relocated |
711 | // because of CodeBuffer expansion. |
712 | if (code->relocation_size() == 0) |
713 | return NULL; |
714 | |
715 | RelocIterator iter(code, call); |
716 | while (iter.next()) { |
717 | if (iter.type() == relocInfo::trampoline_stub_type) { |
718 | if (iter.trampoline_stub_reloc()->owner() == call) { |
719 | return iter.addr(); |
720 | } |
721 | } |
722 | } |
723 | |
724 | return NULL; |
725 | } |
726 | |
727 | bool static_stub_Relocation::clear_inline_cache() { |
728 | // Call stub is only used when calling the interpreted code. |
729 | // It does not really need to be cleared, except that we want to clean out the methodoop. |
730 | CompiledDirectStaticCall::set_stub_to_clean(this); |
731 | return true; |
732 | } |
733 | |
734 | |
735 | void external_word_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { |
736 | address target = _target; |
737 | if (target == NULL) { |
738 | // An absolute embedded reference to an external location, |
739 | // which means there is nothing to fix here. |
740 | return; |
741 | } |
742 | // Probably this reference is absolute, not relative, so the |
743 | // following is probably a no-op. |
744 | assert(src->section_index_of(target) == CodeBuffer::SECT_NONE, "sanity" ); |
745 | set_value(target); |
746 | } |
747 | |
748 | |
749 | address external_word_Relocation::target() { |
750 | address target = _target; |
751 | if (target == NULL) { |
752 | target = pd_get_address_from_code(); |
753 | } |
754 | return target; |
755 | } |
756 | |
757 | |
758 | void internal_word_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { |
759 | address target = _target; |
760 | if (target == NULL) { |
761 | target = new_addr_for(this->target(), src, dest); |
762 | } |
763 | set_value(target); |
764 | } |
765 | |
766 | |
767 | address internal_word_Relocation::target() { |
768 | address target = _target; |
769 | if (target == NULL) { |
770 | if (addr_in_const()) { |
771 | target = *(address*)addr(); |
772 | } else { |
773 | target = pd_get_address_from_code(); |
774 | } |
775 | } |
776 | return target; |
777 | } |
778 | |
779 | //--------------------------------------------------------------------------------- |
780 | // Non-product code |
781 | |
782 | #ifndef PRODUCT |
783 | |
784 | static const char* reloc_type_string(relocInfo::relocType t) { |
785 | switch (t) { |
786 | #define EACH_CASE(name) \ |
787 | case relocInfo::name##_type: \ |
788 | return #name; |
789 | |
790 | APPLY_TO_RELOCATIONS(EACH_CASE); |
791 | #undef EACH_CASE |
792 | |
793 | case relocInfo::none: |
794 | return "none" ; |
795 | case relocInfo::data_prefix_tag: |
796 | return "prefix" ; |
797 | default: |
798 | return "UNKNOWN RELOC TYPE" ; |
799 | } |
800 | } |
801 | |
802 | |
803 | void RelocIterator::print_current() { |
804 | if (!has_current()) { |
805 | tty->print_cr("(no relocs)" ); |
806 | return; |
807 | } |
808 | tty->print("relocInfo@" INTPTR_FORMAT " [type=%d(%s) addr=" INTPTR_FORMAT " offset=%d" , |
809 | p2i(_current), type(), reloc_type_string((relocInfo::relocType) type()), p2i(_addr), _current->addr_offset()); |
810 | if (current()->format() != 0) |
811 | tty->print(" format=%d" , current()->format()); |
812 | if (datalen() == 1) { |
813 | tty->print(" data=%d" , data()[0]); |
814 | } else if (datalen() > 0) { |
815 | tty->print(" data={" ); |
816 | for (int i = 0; i < datalen(); i++) { |
817 | tty->print("%04x" , data()[i] & 0xFFFF); |
818 | } |
819 | tty->print("}" ); |
820 | } |
821 | tty->print("]" ); |
822 | switch (type()) { |
823 | case relocInfo::oop_type: |
824 | { |
825 | oop_Relocation* r = oop_reloc(); |
826 | oop* oop_addr = NULL; |
827 | oop raw_oop = NULL; |
828 | oop oop_value = NULL; |
829 | if (code() != NULL || r->oop_is_immediate()) { |
830 | oop_addr = r->oop_addr(); |
831 | raw_oop = *oop_addr; |
832 | oop_value = r->oop_value(); |
833 | } |
834 | tty->print(" | [oop_addr=" INTPTR_FORMAT " *=" INTPTR_FORMAT " offset=%d]" , |
835 | p2i(oop_addr), p2i(raw_oop), r->offset()); |
836 | // Do not print the oop by default--we want this routine to |
837 | // work even during GC or other inconvenient times. |
838 | if (WizardMode && oop_value != NULL) { |
839 | tty->print("oop_value=" INTPTR_FORMAT ": " , p2i(oop_value)); |
840 | if (oopDesc::is_oop(oop_value)) { |
841 | oop_value->print_value_on(tty); |
842 | } |
843 | } |
844 | break; |
845 | } |
846 | case relocInfo::metadata_type: |
847 | { |
848 | metadata_Relocation* r = metadata_reloc(); |
849 | Metadata** metadata_addr = NULL; |
850 | Metadata* raw_metadata = NULL; |
851 | Metadata* metadata_value = NULL; |
852 | if (code() != NULL || r->metadata_is_immediate()) { |
853 | metadata_addr = r->metadata_addr(); |
854 | raw_metadata = *metadata_addr; |
855 | metadata_value = r->metadata_value(); |
856 | } |
857 | tty->print(" | [metadata_addr=" INTPTR_FORMAT " *=" INTPTR_FORMAT " offset=%d]" , |
858 | p2i(metadata_addr), p2i(raw_metadata), r->offset()); |
859 | if (metadata_value != NULL) { |
860 | tty->print("metadata_value=" INTPTR_FORMAT ": " , p2i(metadata_value)); |
861 | metadata_value->print_value_on(tty); |
862 | } |
863 | break; |
864 | } |
865 | case relocInfo::external_word_type: |
866 | case relocInfo::internal_word_type: |
867 | case relocInfo::section_word_type: |
868 | { |
869 | DataRelocation* r = (DataRelocation*) reloc(); |
870 | tty->print(" | [target=" INTPTR_FORMAT "]" , p2i(r->value())); //value==target |
871 | break; |
872 | } |
873 | case relocInfo::static_call_type: |
874 | { |
875 | static_call_Relocation* r = (static_call_Relocation*) reloc(); |
876 | tty->print(" | [destination=" INTPTR_FORMAT " metadata=" INTPTR_FORMAT "]" , |
877 | p2i(r->destination()), p2i(r->method_value())); |
878 | break; |
879 | } |
880 | case relocInfo::runtime_call_type: |
881 | case relocInfo::runtime_call_w_cp_type: |
882 | { |
883 | CallRelocation* r = (CallRelocation*) reloc(); |
884 | tty->print(" | [destination=" INTPTR_FORMAT "]" , p2i(r->destination())); |
885 | break; |
886 | } |
887 | case relocInfo::virtual_call_type: |
888 | { |
889 | virtual_call_Relocation* r = (virtual_call_Relocation*) reloc(); |
890 | tty->print(" | [destination=" INTPTR_FORMAT " cached_value=" INTPTR_FORMAT " metadata=" INTPTR_FORMAT "]" , |
891 | p2i(r->destination()), p2i(r->cached_value()), p2i(r->method_value())); |
892 | break; |
893 | } |
894 | case relocInfo::static_stub_type: |
895 | { |
896 | static_stub_Relocation* r = (static_stub_Relocation*) reloc(); |
897 | tty->print(" | [static_call=" INTPTR_FORMAT "]" , p2i(r->static_call())); |
898 | break; |
899 | } |
900 | case relocInfo::trampoline_stub_type: |
901 | { |
902 | trampoline_stub_Relocation* r = (trampoline_stub_Relocation*) reloc(); |
903 | tty->print(" | [trampoline owner=" INTPTR_FORMAT "]" , p2i(r->owner())); |
904 | break; |
905 | } |
906 | case relocInfo::opt_virtual_call_type: |
907 | { |
908 | opt_virtual_call_Relocation* r = (opt_virtual_call_Relocation*) reloc(); |
909 | tty->print(" | [destination=" INTPTR_FORMAT " metadata=" INTPTR_FORMAT "]" , |
910 | p2i(r->destination()), p2i(r->method_value())); |
911 | break; |
912 | } |
913 | default: |
914 | break; |
915 | } |
916 | tty->cr(); |
917 | } |
918 | |
919 | |
920 | void RelocIterator::print() { |
921 | RelocIterator save_this = (*this); |
922 | relocInfo* scan = _current; |
923 | if (!has_current()) scan += 1; // nothing to scan here! |
924 | |
925 | bool skip_next = has_current(); |
926 | bool got_next; |
927 | while (true) { |
928 | got_next = (skip_next || next()); |
929 | skip_next = false; |
930 | |
931 | tty->print(" @" INTPTR_FORMAT ": " , p2i(scan)); |
932 | relocInfo* newscan = _current+1; |
933 | if (!has_current()) newscan -= 1; // nothing to scan here! |
934 | while (scan < newscan) { |
935 | tty->print("%04x" , *(short*)scan & 0xFFFF); |
936 | scan++; |
937 | } |
938 | tty->cr(); |
939 | |
940 | if (!got_next) break; |
941 | print_current(); |
942 | } |
943 | |
944 | (*this) = save_this; |
945 | } |
946 | |
947 | // For the debugger: |
948 | extern "C" |
949 | void print_blob_locs(nmethod* nm) { |
950 | nm->print(); |
951 | RelocIterator iter(nm); |
952 | iter.print(); |
953 | } |
954 | extern "C" |
955 | void print_buf_locs(CodeBuffer* cb) { |
956 | FlagSetting fs(PrintRelocations, true); |
957 | cb->print(); |
958 | } |
959 | #endif // !PRODUCT |
960 | |