Bug Summary

File:jdk/src/hotspot/share/code/relocInfo.hpp
Warning:line 512, column 7
Value assigned to field '_databuf' in implicit constructor is garbage or undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name relocInfo.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/libjvm/objs/precompiled -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D _GNU_SOURCE -D _REENTRANT -D LIBC=gnu -D LINUX -D VM_LITTLE_ENDIAN -D _LP64=1 -D ASSERT -D CHECK_UNHANDLED_OOPS -D TARGET_ARCH_x86 -D INCLUDE_SUFFIX_OS=_linux -D INCLUDE_SUFFIX_CPU=_x86 -D INCLUDE_SUFFIX_COMPILER=_gcc -D TARGET_COMPILER_gcc -D AMD64 -D HOTSPOT_LIB_ARCH="amd64" -D COMPILER1 -D COMPILER2 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc/adfiles -I /home/daniel/Projects/java/jdk/src/hotspot/share -I /home/daniel/Projects/java/jdk/src/hotspot/os/linux -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix -I /home/daniel/Projects/java/jdk/src/hotspot/cpu/x86 -I /home/daniel/Projects/java/jdk/src/hotspot/os_cpu/linux_x86 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc -I /home/daniel/Projects/java/jdk/src/hotspot/share/precompiled -I /home/daniel/Projects/java/jdk/src/hotspot/share/include -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix/include -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base/linux -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libjimage -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc/adfiles -I /home/daniel/Projects/java/jdk/src/hotspot/share -I /home/daniel/Projects/java/jdk/src/hotspot/os/linux -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix -I /home/daniel/Projects/java/jdk/src/hotspot/cpu/x86 -I /home/daniel/Projects/java/jdk/src/hotspot/os_cpu/linux_x86 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc -D _FORTIFY_SOURCE=2 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-format-zero-length -Wno-unused-parameter -Wno-unused -Wno-parentheses -Wno-comment -Wno-unknown-pragmas -Wno-address -Wno-delete-non-virtual-dtor -Wno-char-subscripts -Wno-array-bounds -Wno-int-in-bool-context -Wno-ignored-qualifiers -Wno-missing-field-initializers -Wno-implicit-fallthrough -Wno-empty-body -Wno-strict-overflow -Wno-sequence-point -Wno-maybe-uninitialized -Wno-misleading-indentation -Wno-cast-function-type -Wno-shift-negative-value -std=c++14 -fdeprecated-macro -fdebug-compilation-dir /home/daniel/Projects/java/jdk/make/hotspot -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -stack-protector 1 -fno-rtti -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/daniel/Projects/java/scan/2021-12-21-193737-8510-1 -x c++ /home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.cpp

/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.cpp

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

/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp

1/*
2 * Copyright (c) 1997, 2021, 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#ifndef SHARE_CODE_RELOCINFO_HPP
26#define SHARE_CODE_RELOCINFO_HPP
27
28#include "runtime/os.hpp"
29#include "utilities/macros.hpp"
30
31class nmethod;
32class CodeBlob;
33class CompiledMethod;
34class Metadata;
35class NativeMovConstReg;
36
37// Types in this file:
38// relocInfo
39// One element of an array of halfwords encoding compressed relocations.
40// Also, the source of relocation types (relocInfo::oop_type, ...).
41// Relocation
42// A flyweight object representing a single relocation.
43// It is fully unpacked from the compressed relocation array.
44// metadata_Relocation, ... (subclasses of Relocation)
45// The location of some type-specific operations (metadata_addr, ...).
46// Also, the source of relocation specs (metadata_Relocation::spec, ...).
47// oop_Relocation, ... (subclasses of Relocation)
48// oops in the code stream (strings, class loaders)
49// Also, the source of relocation specs (oop_Relocation::spec, ...).
50// RelocationHolder
51// A value type which acts as a union holding a Relocation object.
52// Represents a relocation spec passed into a CodeBuffer during assembly.
53// RelocIterator
54// A StackObj which iterates over the relocations associated with
55// a range of code addresses. Can be used to operate a copy of code.
56
57
58// Notes on relocType:
59//
60// These hold enough information to read or write a value embedded in
61// the instructions of an CodeBlob. They're used to update:
62//
63// 1) embedded oops (isOop() == true)
64// 2) inline caches (isIC() == true)
65// 3) runtime calls (isRuntimeCall() == true)
66// 4) internal word ref (isInternalWord() == true)
67// 5) external word ref (isExternalWord() == true)
68//
69// when objects move (GC) or if code moves (compacting the code heap).
70// They are also used to patch the code (if a call site must change)
71//
72// A relocInfo is represented in 16 bits:
73// 4 bits indicating the relocation type
74// 12 bits indicating the offset from the previous relocInfo address
75//
76// The offsets accumulate along the relocInfo stream to encode the
77// address within the CodeBlob, which is named RelocIterator::addr().
78// The address of a particular relocInfo always points to the first
79// byte of the relevant instruction (and not to any of its subfields
80// or embedded immediate constants).
81//
82// The offset value is scaled appropriately for the target machine.
83// (See relocInfo_<arch>.hpp for the offset scaling.)
84//
85// On some machines, there may also be a "format" field which may provide
86// additional information about the format of the instruction stream
87// at the corresponding code address. The format value is usually zero.
88// Any machine (such as Intel) whose instructions can sometimes contain
89// more than one relocatable constant needs format codes to distinguish
90// which operand goes with a given relocation.
91//
92// If the target machine needs N format bits, the offset has 12-N bits,
93// the format is encoded between the offset and the type, and the
94// relocInfo_<arch>.hpp file has manifest constants for the format codes.
95//
96// If the type is "data_prefix_tag" then the offset bits are further encoded,
97// and in fact represent not a code-stream offset but some inline data.
98// The data takes the form of a counted sequence of halfwords, which
99// precedes the actual relocation record. (Clients never see it directly.)
100// The interpetation of this extra data depends on the relocation type.
101//
102// On machines that have 32-bit immediate fields, there is usually
103// little need for relocation "prefix" data, because the instruction stream
104// is a perfectly reasonable place to store the value. On machines in
105// which 32-bit values must be "split" across instructions, the relocation
106// data is the "true" specification of the value, which is then applied
107// to some field of the instruction (22 or 13 bits, on SPARC).
108//
109// Whenever the location of the CodeBlob changes, any PC-relative
110// relocations, and any internal_word_type relocations, must be reapplied.
111// After the GC runs, oop_type relocations must be reapplied.
112//
113//
114// Here are meanings of the types:
115//
116// relocInfo::none -- a filler record
117// Value: none
118// Instruction: The corresponding code address is ignored
119// Data: Any data prefix and format code are ignored
120// (This means that any relocInfo can be disabled by setting
121// its type to none. See relocInfo::remove.)
122//
123// relocInfo::oop_type, relocInfo::metadata_type -- a reference to an oop or meta data
124// Value: an oop, or else the address (handle) of an oop
125// Instruction types: memory (load), set (load address)
126// Data: [] an oop stored in 4 bytes of instruction
127// [n] n is the index of an oop in the CodeBlob's oop pool
128// [[N]n l] and l is a byte offset to be applied to the oop
129// [Nn Ll] both index and offset may be 32 bits if necessary
130// Here is a special hack, used only by the old compiler:
131// [[N]n 00] the value is the __address__ of the nth oop in the pool
132// (Note that the offset allows optimal references to class variables.)
133//
134// relocInfo::internal_word_type -- an address within the same CodeBlob
135// relocInfo::section_word_type -- same, but can refer to another section
136// Value: an address in the CodeBlob's code or constants section
137// Instruction types: memory (load), set (load address)
138// Data: [] stored in 4 bytes of instruction
139// [[L]l] a relative offset (see [About Offsets] below)
140// In the case of section_word_type, the offset is relative to a section
141// base address, and the section number (e.g., SECT_INSTS) is encoded
142// into the low two bits of the offset L.
143//
144// relocInfo::external_word_type -- a fixed address in the runtime system
145// Value: an address
146// Instruction types: memory (load), set (load address)
147// Data: [] stored in 4 bytes of instruction
148// [n] the index of a "well-known" stub (usual case on RISC)
149// [Ll] a 32-bit address
150//
151// relocInfo::runtime_call_type -- a fixed subroutine in the runtime system
152// Value: an address
153// Instruction types: PC-relative call (or a PC-relative branch)
154// Data: [] stored in 4 bytes of instruction
155//
156// relocInfo::static_call_type -- a static call
157// Value: an CodeBlob, a stub, or a fixup routine
158// Instruction types: a call
159// Data: []
160// The identity of the callee is extracted from debugging information.
161// //%note reloc_3
162//
163// relocInfo::virtual_call_type -- a virtual call site (which includes an inline
164// cache)
165// Value: an CodeBlob, a stub, the interpreter, or a fixup routine
166// Instruction types: a call, plus some associated set-oop instructions
167// Data: [] the associated set-oops are adjacent to the call
168// [n] n is a relative offset to the first set-oop
169// [[N]n l] and l is a limit within which the set-oops occur
170// [Nn Ll] both n and l may be 32 bits if necessary
171// The identity of the callee is extracted from debugging information.
172//
173// relocInfo::opt_virtual_call_type -- a virtual call site that is statically bound
174//
175// Same info as a static_call_type. We use a special type, so the handling of
176// virtuals and statics are separated.
177//
178//
179// The offset n points to the first set-oop. (See [About Offsets] below.)
180// In turn, the set-oop instruction specifies or contains an oop cell devoted
181// exclusively to the IC call, which can be patched along with the call.
182//
183// The locations of any other set-oops are found by searching the relocation
184// information starting at the first set-oop, and continuing until all
185// relocations up through l have been inspected. The value l is another
186// relative offset. (Both n and l are relative to the call's first byte.)
187//
188// The limit l of the search is exclusive. However, if it points within
189// the call (e.g., offset zero), it is adjusted to point after the call and
190// any associated machine-specific delay slot.
191//
192// Since the offsets could be as wide as 32-bits, these conventions
193// put no restrictions whatever upon code reorganization.
194//
195// The compiler is responsible for ensuring that transition from a clean
196// state to a monomorphic compiled state is MP-safe. This implies that
197// the system must respond well to intermediate states where a random
198// subset of the set-oops has been correctly from the clean state
199// upon entry to the VEP of the compiled method. In the case of a
200// machine (Intel) with a single set-oop instruction, the 32-bit
201// immediate field must not straddle a unit of memory coherence.
202// //%note reloc_3
203//
204// relocInfo::static_stub_type -- an extra stub for each static_call_type
205// Value: none
206// Instruction types: a virtual call: { set_oop; jump; }
207// Data: [[N]n] the offset of the associated static_call reloc
208// This stub becomes the target of a static call which must be upgraded
209// to a virtual call (because the callee is interpreted).
210// See [About Offsets] below.
211// //%note reloc_2
212//
213// relocInfo::poll_[return_]type -- a safepoint poll
214// Value: none
215// Instruction types: memory load or test
216// Data: none
217//
218// For example:
219//
220// INSTRUCTIONS RELOC: TYPE PREFIX DATA
221// ------------ ---- -----------
222// sethi %hi(myObject), R oop_type [n(myObject)]
223// ld [R+%lo(myObject)+fldOffset], R2 oop_type [n(myObject) fldOffset]
224// add R2, 1, R2
225// st R2, [R+%lo(myObject)+fldOffset] oop_type [n(myObject) fldOffset]
226//%note reloc_1
227//
228// This uses 4 instruction words, 8 relocation halfwords,
229// and an entry (which is sharable) in the CodeBlob's oop pool,
230// for a total of 36 bytes.
231//
232// Note that the compiler is responsible for ensuring the "fldOffset" when
233// added to "%lo(myObject)" does not overflow the immediate fields of the
234// memory instructions.
235//
236//
237// [About Offsets] Relative offsets are supplied to this module as
238// positive byte offsets, but they may be internally stored scaled
239// and/or negated, depending on what is most compact for the target
240// system. Since the object pointed to by the offset typically
241// precedes the relocation address, it is profitable to store
242// these negative offsets as positive numbers, but this decision
243// is internal to the relocation information abstractions.
244//
245
246class Relocation;
247class CodeBuffer;
248class CodeSection;
249class RelocIterator;
250
251class relocInfo {
252 friend class RelocIterator;
253 public:
254 enum relocType {
255 none = 0, // Used when no relocation should be generated
256 oop_type = 1, // embedded oop
257 virtual_call_type = 2, // a standard inline cache call for a virtual send
258 opt_virtual_call_type = 3, // a virtual call that has been statically bound (i.e., no IC cache)
259 static_call_type = 4, // a static send
260 static_stub_type = 5, // stub-entry for static send (takes care of interpreter case)
261 runtime_call_type = 6, // call to fixed external routine
262 external_word_type = 7, // reference to fixed external address
263 internal_word_type = 8, // reference within the current code blob
264 section_word_type = 9, // internal, but a cross-section reference
265 poll_type = 10, // polling instruction for safepoints
266 poll_return_type = 11, // polling instruction for safepoints at return
267 metadata_type = 12, // metadata that used to be oops
268 trampoline_stub_type = 13, // stub-entry for trampoline
269 runtime_call_w_cp_type = 14, // Runtime call which may load its target from the constant pool
270 data_prefix_tag = 15, // tag for a prefix (carries data arguments)
271 type_mask = 15 // A mask which selects only the above values
272 };
273
274 private:
275 unsigned short _value;
276
277 static const enum class RawBitsToken {} RAW_BITS{};
278
279 relocInfo(relocType type, RawBitsToken, int bits)
280 : _value((type << nontype_width) + bits) { }
281
282 static relocType check_relocType(relocType type) NOT_DEBUG({ return type; });
283
284 static void check_offset_and_format(int offset, int format) NOT_DEBUG_RETURN;
285
286 static int compute_bits(int offset, int format) {
287 check_offset_and_format(offset, format);
288 return (offset / offset_unit) + (format << offset_width);
289 }
290
291 public:
292 relocInfo(relocType type, int offset, int format = 0)
293 : relocInfo(check_relocType(type), RAW_BITS, compute_bits(offset, format)) {}
294
295 #define APPLY_TO_RELOCATIONS(visitor)visitor(oop) visitor(metadata) visitor(virtual_call) visitor(
opt_virtual_call) visitor(static_call) visitor(static_stub) visitor
(runtime_call) visitor(runtime_call_w_cp) visitor(external_word
) visitor(internal_word) visitor(poll) visitor(poll_return) visitor
(section_word) visitor(trampoline_stub)
\
296 visitor(oop) \
297 visitor(metadata) \
298 visitor(virtual_call) \
299 visitor(opt_virtual_call) \
300 visitor(static_call) \
301 visitor(static_stub) \
302 visitor(runtime_call) \
303 visitor(runtime_call_w_cp) \
304 visitor(external_word) \
305 visitor(internal_word) \
306 visitor(poll) \
307 visitor(poll_return) \
308 visitor(section_word) \
309 visitor(trampoline_stub) \
310
311
312 public:
313 enum {
314 value_width = sizeof(unsigned short) * BitsPerByte,
315 type_width = 4, // == log2(type_mask+1)
316 nontype_width = value_width - type_width,
317 datalen_width = nontype_width-1,
318 datalen_tag = 1 << datalen_width, // or-ed into _value
319 datalen_limit = 1 << datalen_width,
320 datalen_mask = (1 << datalen_width)-1
321 };
322
323 // accessors
324 public:
325 relocType type() const { return (relocType)((unsigned)_value >> nontype_width); }
326 int format() const { return format_mask==0? 0: format_mask &
327 ((unsigned)_value >> offset_width); }
328 int addr_offset() const { assert(!is_prefix(), "must have offset")do { if (!(!is_prefix())) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 328, "assert(" "!is_prefix()" ") failed", "must have offset"
); ::breakpoint(); } } while (0)
;
329 return (_value & offset_mask)*offset_unit; }
330
331 protected:
332 const short* data() const { assert(is_datalen(), "must have data")do { if (!(is_datalen())) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 332, "assert(" "is_datalen()" ") failed", "must have data")
; ::breakpoint(); } } while (0)
;
333 return (const short*)(this + 1); }
334 int datalen() const { assert(is_datalen(), "must have data")do { if (!(is_datalen())) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 334, "assert(" "is_datalen()" ") failed", "must have data")
; ::breakpoint(); } } while (0)
;
335 return (_value & datalen_mask); }
336 int immediate() const { assert(is_immediate(), "must have immed")do { if (!(is_immediate())) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 336, "assert(" "is_immediate()" ") failed", "must have immed"
); ::breakpoint(); } } while (0)
;
337 return (_value & datalen_mask); }
338 public:
339 static int addr_unit() { return offset_unit; }
340 static int offset_limit() { return (1 << offset_width) * offset_unit; }
341
342 void set_type(relocType type);
343
344 void remove() { set_type(none); }
345
346 protected:
347 bool is_none() const { return type() == none; }
348 bool is_prefix() const { return type() == data_prefix_tag; }
349 bool is_datalen() const { assert(is_prefix(), "must be prefix")do { if (!(is_prefix())) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 349, "assert(" "is_prefix()" ") failed", "must be prefix");
::breakpoint(); } } while (0)
;
350 return (_value & datalen_tag) != 0; }
351 bool is_immediate() const { assert(is_prefix(), "must be prefix")do { if (!(is_prefix())) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 351, "assert(" "is_prefix()" ") failed", "must be prefix");
::breakpoint(); } } while (0)
;
352 return (_value & datalen_tag) == 0; }
353
354 public:
355 // Occasionally records of type relocInfo::none will appear in the stream.
356 // We do not bother to filter these out, but clients should ignore them.
357 // These records serve as "filler" in three ways:
358 // - to skip large spans of unrelocated code (this is rare)
359 // - to pad out the relocInfo array to the required oop alignment
360 // - to disable old relocation information which is no longer applicable
361
362 inline friend relocInfo filler_relocInfo();
363
364 // Every non-prefix relocation may be preceded by at most one prefix,
365 // which supplies 1 or more halfwords of associated data. Conventionally,
366 // an int is represented by 0, 1, or 2 halfwords, depending on how
367 // many bits are required to represent the value. (In addition,
368 // if the sole halfword is a 10-bit unsigned number, it is made
369 // "immediate" in the prefix header word itself. This optimization
370 // is invisible outside this module.)
371
372 inline friend relocInfo prefix_relocInfo(int datalen);
373
374 private:
375 // an immediate relocInfo optimizes a prefix with one 10-bit unsigned value
376 static relocInfo immediate_relocInfo(int data0) {
377 assert(fits_into_immediate(data0), "data0 in limits")do { if (!(fits_into_immediate(data0))) { (*g_assert_poison) =
'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 377, "assert(" "fits_into_immediate(data0)" ") failed", "data0 in limits"
); ::breakpoint(); } } while (0)
;
378 return relocInfo(relocInfo::data_prefix_tag, RAW_BITS, data0);
379 }
380 static bool fits_into_immediate(int data0) {
381 return (data0 >= 0 && data0 < datalen_limit);
382 }
383
384 public:
385 // Support routines for compilers.
386
387 // This routine takes an infant relocInfo (unprefixed) and
388 // edits in its prefix, if any. It also updates dest.locs_end.
389 void initialize(CodeSection* dest, Relocation* reloc);
390
391 // This routine updates a prefix and returns the limit pointer.
392 // It tries to compress the prefix from 32 to 16 bits, and if
393 // successful returns a reduced "prefix_limit" pointer.
394 relocInfo* finish_prefix(short* prefix_limit);
395
396 // bit-packers for the data array:
397
398 // As it happens, the bytes within the shorts are ordered natively,
399 // but the shorts within the word are ordered big-endian.
400 // This is an arbitrary choice, made this way mainly to ease debugging.
401 static int data0_from_int(jint x) { return x >> value_width; }
402 static int data1_from_int(jint x) { return (short)x; }
403 static jint jint_from_data(short* data) {
404 return (data[0] << value_width) + (unsigned short)data[1];
405 }
406
407 static jint short_data_at(int n, short* data, int datalen) {
408 return datalen > n ? data[n] : 0;
409 }
410
411 static jint jint_data_at(int n, short* data, int datalen) {
412 return datalen > n+1 ? jint_from_data(&data[n]) : short_data_at(n, data, datalen);
413 }
414
415 // Update methods for relocation information
416 // (since code is dynamically patched, we also need to dynamically update the relocation info)
417 // Both methods takes old_type, so it is able to performe sanity checks on the information removed.
418 static void change_reloc_info_for_address(RelocIterator *itr, address pc, relocType old_type, relocType new_type);
419
420 // Machine dependent stuff
421#include CPU_HEADER(relocInfo)"relocInfo_x86.hpp"
422
423 protected:
424 // Derived constant, based on format_width which is PD:
425 enum {
426 offset_width = nontype_width - format_width,
427 offset_mask = (1<<offset_width) - 1,
428 format_mask = (1<<format_width) - 1
429 };
430 public:
431 enum {
432#ifdef _LP641
433 // for use in format
434 // format_width must be at least 1 on _LP64
435 narrow_oop_in_const = 1,
436#endif
437 // Conservatively large estimate of maximum length (in shorts)
438 // of any relocation record.
439 // Extended format is length prefix, data words, and tag/offset suffix.
440 length_limit = 1 + 1 + (3*BytesPerWord/BytesPerShort) + 1,
441 have_format = format_width > 0
442 };
443};
444
445#define FORWARD_DECLARE_EACH_CLASS(name) \
446class name##_Relocation;
447APPLY_TO_RELOCATIONS(FORWARD_DECLARE_EACH_CLASS)FORWARD_DECLARE_EACH_CLASS(oop) FORWARD_DECLARE_EACH_CLASS(metadata
) FORWARD_DECLARE_EACH_CLASS(virtual_call) FORWARD_DECLARE_EACH_CLASS
(opt_virtual_call) FORWARD_DECLARE_EACH_CLASS(static_call) FORWARD_DECLARE_EACH_CLASS
(static_stub) FORWARD_DECLARE_EACH_CLASS(runtime_call) FORWARD_DECLARE_EACH_CLASS
(runtime_call_w_cp) FORWARD_DECLARE_EACH_CLASS(external_word)
FORWARD_DECLARE_EACH_CLASS(internal_word) FORWARD_DECLARE_EACH_CLASS
(poll) FORWARD_DECLARE_EACH_CLASS(poll_return) FORWARD_DECLARE_EACH_CLASS
(section_word) FORWARD_DECLARE_EACH_CLASS(trampoline_stub)
448#undef FORWARD_DECLARE_EACH_CLASS
449
450
451
452inline relocInfo filler_relocInfo() {
453 return relocInfo(relocInfo::none, relocInfo::offset_limit() - relocInfo::offset_unit);
454}
455
456inline relocInfo prefix_relocInfo(int datalen = 0) {
457 assert(relocInfo::fits_into_immediate(datalen), "datalen in limits")do { if (!(relocInfo::fits_into_immediate(datalen))) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 457, "assert(" "relocInfo::fits_into_immediate(datalen)" ") failed"
, "datalen in limits"); ::breakpoint(); } } while (0)
;
458 return relocInfo(relocInfo::data_prefix_tag, relocInfo::RAW_BITS, relocInfo::datalen_tag | datalen);
459}
460
461
462// Holder for flyweight relocation objects.
463// Although the flyweight subclasses are of varying sizes,
464// the holder is "one size fits all".
465class RelocationHolder {
466 friend class Relocation;
467 friend class CodeSection;
468
469 private:
470 // this preallocated memory must accommodate all subclasses of Relocation
471 // (this number is assertion-checked in Relocation::operator new)
472 enum { _relocbuf_size = 5 };
473 void* _relocbuf[ _relocbuf_size ];
474
475 public:
476 Relocation* reloc() const { return (Relocation*) &_relocbuf[0]; }
477 inline relocInfo::relocType type() const;
478
479 // Add a constant offset to a relocation. Helper for class Address.
480 RelocationHolder plus(int offset) const;
481
482 inline RelocationHolder(); // initializes type to none
483
484 inline RelocationHolder(Relocation* r); // make a copy
485
486 static const RelocationHolder none;
487};
488
489// A RelocIterator iterates through the relocation information of a CodeBlob.
490// It provides access to successive relocations as it is advanced through a
491// code stream.
492// Usage:
493// RelocIterator iter(nm);
494// while (iter.next()) {
495// iter.reloc()->some_operation();
496// }
497// or:
498// RelocIterator iter(nm);
499// while (iter.next()) {
500// switch (iter.type()) {
501// case relocInfo::oop_type :
502// case relocInfo::ic_type :
503// case relocInfo::prim_type :
504// case relocInfo::uncommon_type :
505// case relocInfo::runtime_call_type :
506// case relocInfo::internal_word_type:
507// case relocInfo::external_word_type:
508// ...
509// }
510// }
511
512class RelocIterator : public StackObj {
3
Value assigned to field '_databuf' in implicit constructor is garbage or undefined
513 friend class section_word_Relocation; // for section verification
514 enum { SECT_LIMIT = 3 }; // must be equal to CodeBuffer::SECT_LIMIT, checked in ctor
515 friend class Relocation;
516 friend class relocInfo; // for change_reloc_info_for_address only
517 typedef relocInfo::relocType relocType;
518
519 private:
520 address _limit; // stop producing relocations after this _addr
521 relocInfo* _current; // the current relocation information
522 relocInfo* _end; // end marker; we're done iterating when _current == _end
523 CompiledMethod* _code; // compiled method containing _addr
524 address _addr; // instruction to which the relocation applies
525 short _databuf; // spare buffer for compressed data
526 short* _data; // pointer to the relocation's data
527 short _datalen; // number of halfwords in _data
528
529 // Base addresses needed to compute targets of section_word_type relocs.
530 address _section_start[SECT_LIMIT];
531 address _section_end [SECT_LIMIT];
532
533 void set_has_current(bool b) {
534 _datalen = !b ? -1 : 0;
535 debug_only(_data = NULL)_data = __null;
536 }
537 void set_current(relocInfo& ri) {
538 _current = &ri;
539 set_has_current(true);
540 }
541
542 RelocationHolder _rh; // where the current relocation is allocated
543
544 relocInfo* current() const { assert(has_current(), "must have current")do { if (!(has_current())) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 544, "assert(" "has_current()" ") failed", "must have current"
); ::breakpoint(); } } while (0)
;
545 return _current; }
546
547 void set_limits(address begin, address limit);
548
549 void advance_over_prefix(); // helper method
550
551 void initialize_misc();
552
553 void initialize(CompiledMethod* nm, address begin, address limit);
554
555 RelocIterator() { initialize_misc(); }
556
557 public:
558 // constructor
559 RelocIterator(CompiledMethod* nm, address begin = NULL__null, address limit = NULL__null);
560 RelocIterator(CodeSection* cb, address begin = NULL__null, address limit = NULL__null);
561
562 // get next reloc info, return !eos
563 bool next() {
564 _current++;
565 assert(_current <= _end, "must not overrun relocInfo")do { if (!(_current <= _end)) { (*g_assert_poison) = 'X';;
report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 565, "assert(" "_current <= _end" ") failed", "must not overrun relocInfo"
); ::breakpoint(); } } while (0)
;
566 if (_current == _end) {
567 set_has_current(false);
568 return false;
569 }
570 set_has_current(true);
571
572 if (_current->is_prefix()) {
573 advance_over_prefix();
574 assert(!current()->is_prefix(), "only one prefix at a time")do { if (!(!current()->is_prefix())) { (*g_assert_poison) =
'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 574, "assert(" "!current()->is_prefix()" ") failed", "only one prefix at a time"
); ::breakpoint(); } } while (0)
;
575 }
576
577 _addr += _current->addr_offset();
578
579 if (_limit != NULL__null && _addr >= _limit) {
580 set_has_current(false);
581 return false;
582 }
583
584 return true;
585 }
586
587 // accessors
588 address limit() const { return _limit; }
589 relocType type() const { return current()->type(); }
590 int format() const { return (relocInfo::have_format) ? current()->format() : 0; }
591 address addr() const { return _addr; }
592 CompiledMethod* code() const { return _code; }
593 short* data() const { return _data; }
594 int datalen() const { return _datalen; }
595 bool has_current() const { return _datalen >= 0; }
596 bool addr_in_const() const;
597
598 address section_start(int n) const {
599 assert(_section_start[n], "must be initialized")do { if (!(_section_start[n])) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 599, "assert(" "_section_start[n]" ") failed", "must be initialized"
); ::breakpoint(); } } while (0)
;
600 return _section_start[n];
601 }
602 address section_end(int n) const {
603 assert(_section_end[n], "must be initialized")do { if (!(_section_end[n])) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 603, "assert(" "_section_end[n]" ") failed", "must be initialized"
); ::breakpoint(); } } while (0)
;
604 return _section_end[n];
605 }
606
607 // The address points to the affected displacement part of the instruction.
608 // For RISC, this is just the whole instruction.
609 // For Intel, this is an unaligned 32-bit word.
610
611 // type-specific relocation accessors: oop_Relocation* oop_reloc(), etc.
612 #define EACH_TYPE(name) \
613 inline name##_Relocation* name##_reloc();
614 APPLY_TO_RELOCATIONS(EACH_TYPE)EACH_TYPE(oop) EACH_TYPE(metadata) EACH_TYPE(virtual_call) EACH_TYPE
(opt_virtual_call) EACH_TYPE(static_call) EACH_TYPE(static_stub
) EACH_TYPE(runtime_call) EACH_TYPE(runtime_call_w_cp) EACH_TYPE
(external_word) EACH_TYPE(internal_word) EACH_TYPE(poll) EACH_TYPE
(poll_return) EACH_TYPE(section_word) EACH_TYPE(trampoline_stub
)
615 #undef EACH_TYPE
616 // generic relocation accessor; switches on type to call the above
617 Relocation* reloc();
618
619#ifndef PRODUCT
620 public:
621 void print();
622 void print_current();
623#endif
624};
625
626
627// A Relocation is a flyweight object allocated within a RelocationHolder.
628// It represents the relocation data of relocation record.
629// So, the RelocIterator unpacks relocInfos into Relocations.
630
631class Relocation {
632 friend class RelocationHolder;
633 friend class RelocIterator;
634
635 private:
636 // When a relocation has been created by a RelocIterator,
637 // this field is non-null. It allows the relocation to know
638 // its context, such as the address to which it applies.
639 RelocIterator* _binding;
640
641 relocInfo::relocType _rtype;
642
643 protected:
644 RelocIterator* binding() const {
645 assert(_binding != NULL, "must be bound")do { if (!(_binding != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 645, "assert(" "_binding != __null" ") failed", "must be bound"
); ::breakpoint(); } } while (0)
;
646 return _binding;
647 }
648 void set_binding(RelocIterator* b) {
649 assert(_binding == NULL, "must be unbound")do { if (!(_binding == __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 649, "assert(" "_binding == __null" ") failed", "must be unbound"
); ::breakpoint(); } } while (0)
;
650 _binding = b;
651 assert(_binding != NULL, "must now be bound")do { if (!(_binding != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 651, "assert(" "_binding != __null" ") failed", "must now be bound"
); ::breakpoint(); } } while (0)
;
652 }
653
654 Relocation(relocInfo::relocType rtype) : _binding(NULL__null), _rtype(rtype) { }
655
656 static RelocationHolder newHolder() {
657 return RelocationHolder();
658 }
659
660 public:
661 void* operator new(size_t size, const RelocationHolder& holder) throw() {
662 assert(size <= sizeof(holder._relocbuf), "Make _relocbuf bigger!")do { if (!(size <= sizeof(holder._relocbuf))) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 662, "assert(" "size <= sizeof(holder._relocbuf)" ") failed"
, "Make _relocbuf bigger!"); ::breakpoint(); } } while (0)
;
663 assert((void* const *)holder.reloc() == &holder._relocbuf[0], "ptrs must agree")do { if (!((void* const *)holder.reloc() == &holder._relocbuf
[0])) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 663, "assert(" "(void* const *)holder.reloc() == &holder._relocbuf[0]"
") failed", "ptrs must agree"); ::breakpoint(); } } while (0
)
;
664 return holder.reloc();
665 }
666
667 // make a generic relocation for a given type (if possible)
668 static RelocationHolder spec_simple(relocInfo::relocType rtype);
669
670 // here is the type-specific hook which writes relocation data:
671 virtual void pack_data_to(CodeSection* dest) { }
672
673 // here is the type-specific hook which reads (unpacks) relocation data:
674 virtual void unpack_data() {
675 assert(datalen()==0 || type()==relocInfo::none, "no data here")do { if (!(datalen()==0 || type()==relocInfo::none)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 675, "assert(" "datalen()==0 || type()==relocInfo::none" ") failed"
, "no data here"); ::breakpoint(); } } while (0)
;
676 }
677
678 protected:
679 // Helper functions for pack_data_to() and unpack_data().
680
681 // Most of the compression logic is confined here.
682 // (The "immediate data" mechanism of relocInfo works independently
683 // of this stuff, and acts to further compress most 1-word data prefixes.)
684
685 // A variable-width int is encoded as a short if it will fit in 16 bits.
686 // The decoder looks at datalen to decide whether to unpack short or jint.
687 // Most relocation records are quite simple, containing at most two ints.
688
689 static bool is_short(jint x) { return x == (short)x; }
690 static short* add_short(short* p, int x) { *p++ = x; return p; }
691 static short* add_jint (short* p, jint x) {
692 *p++ = relocInfo::data0_from_int(x); *p++ = relocInfo::data1_from_int(x);
693 return p;
694 }
695 static short* add_var_int(short* p, jint x) { // add a variable-width int
696 if (is_short(x)) p = add_short(p, x);
697 else p = add_jint (p, x);
698 return p;
699 }
700
701 static short* pack_1_int_to(short* p, jint x0) {
702 // Format is one of: [] [x] [Xx]
703 if (x0 != 0) p = add_var_int(p, x0);
704 return p;
705 }
706 int unpack_1_int() {
707 assert(datalen() <= 2, "too much data")do { if (!(datalen() <= 2)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 707, "assert(" "datalen() <= 2" ") failed", "too much data"
); ::breakpoint(); } } while (0)
;
708 return relocInfo::jint_data_at(0, data(), datalen());
709 }
710
711 // With two ints, the short form is used only if both ints are short.
712 short* pack_2_ints_to(short* p, jint x0, jint x1) {
713 // Format is one of: [] [x y?] [Xx Y?y]
714 if (x0 == 0 && x1 == 0) {
715 // no halfwords needed to store zeroes
716 } else if (is_short(x0) && is_short(x1)) {
717 // 1-2 halfwords needed to store shorts
718 p = add_short(p, x0); if (x1!=0) p = add_short(p, x1);
719 } else {
720 // 3-4 halfwords needed to store jints
721 p = add_jint(p, x0); p = add_var_int(p, x1);
722 }
723 return p;
724 }
725 void unpack_2_ints(jint& x0, jint& x1) {
726 int dlen = datalen();
727 short* dp = data();
728 if (dlen <= 2) {
729 x0 = relocInfo::short_data_at(0, dp, dlen);
730 x1 = relocInfo::short_data_at(1, dp, dlen);
731 } else {
732 assert(dlen <= 4, "too much data")do { if (!(dlen <= 4)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 732, "assert(" "dlen <= 4" ") failed", "too much data");
::breakpoint(); } } while (0)
;
733 x0 = relocInfo::jint_data_at(0, dp, dlen);
734 x1 = relocInfo::jint_data_at(2, dp, dlen);
735 }
736 }
737
738 protected:
739 // platform-independent utility for patching constant section
740 void const_set_data_value (address x);
741 void const_verify_data_value (address x);
742 // platform-dependent utilities for decoding and patching instructions
743 void pd_set_data_value (address x, intptr_t off, bool verify_only = false); // a set or mem-ref
744 void pd_verify_data_value (address x, intptr_t off) { pd_set_data_value(x, off, true); }
745 address pd_call_destination (address orig_addr = NULL__null);
746 void pd_set_call_destination (address x);
747
748 // this extracts the address of an address in the code stream instead of the reloc data
749 address* pd_address_in_code ();
750
751 // this extracts an address from the code stream instead of the reloc data
752 address pd_get_address_from_code ();
753
754 // these convert from byte offsets, to scaled offsets, to addresses
755 static jint scaled_offset(address x, address base) {
756 int byte_offset = x - base;
757 int offset = -byte_offset / relocInfo::addr_unit();
758 assert(address_from_scaled_offset(offset, base) == x, "just checkin'")do { if (!(address_from_scaled_offset(offset, base) == x)) { (
*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 758, "assert(" "address_from_scaled_offset(offset, base) == x"
") failed", "just checkin'"); ::breakpoint(); } } while (0)
;
759 return offset;
760 }
761 static jint scaled_offset_null_special(address x, address base) {
762 // Some relocations treat offset=0 as meaning NULL.
763 // Handle this extra convention carefully.
764 if (x == NULL__null) return 0;
765 assert(x != base, "offset must not be zero")do { if (!(x != base)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 765, "assert(" "x != base" ") failed", "offset must not be zero"
); ::breakpoint(); } } while (0)
;
766 return scaled_offset(x, base);
767 }
768 static address address_from_scaled_offset(jint offset, address base) {
769 int byte_offset = -( offset * relocInfo::addr_unit() );
770 return base + byte_offset;
771 }
772
773 // helpers for mapping between old and new addresses after a move or resize
774 address old_addr_for(address newa, const CodeBuffer* src, CodeBuffer* dest);
775 address new_addr_for(address olda, const CodeBuffer* src, CodeBuffer* dest);
776 void normalize_address(address& addr, const CodeSection* dest, bool allow_other_sections = false);
777
778 public:
779 // accessors which only make sense for a bound Relocation
780 address addr() const { return binding()->addr(); }
781 CompiledMethod* code() const { return binding()->code(); }
782 bool addr_in_const() const { return binding()->addr_in_const(); }
783 protected:
784 short* data() const { return binding()->data(); }
785 int datalen() const { return binding()->datalen(); }
786 int format() const { return binding()->format(); }
787
788 public:
789 relocInfo::relocType type() const { return _rtype; }
790
791 // is it a call instruction?
792 virtual bool is_call() { return false; }
793
794 // is it a data movement instruction?
795 virtual bool is_data() { return false; }
796
797 // some relocations can compute their own values
798 virtual address value();
799
800 // all relocations are able to reassert their values
801 virtual void set_value(address x);
802
803 virtual bool clear_inline_cache() { return true; }
804
805 // This method assumes that all virtual/static (inline) caches are cleared (since for static_call_type and
806 // ic_call_type is not always posisition dependent (depending on the state of the cache)). However, this is
807 // probably a reasonable assumption, since empty caches simplifies code reloacation.
808 virtual void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { }
809};
810
811
812// certain inlines must be deferred until class Relocation is defined:
813
814inline RelocationHolder::RelocationHolder() {
815 // initialize the vtbl, just to keep things type-safe
816 new(*this) Relocation(relocInfo::none);
817}
818
819
820inline RelocationHolder::RelocationHolder(Relocation* r) {
821 // wordwise copy from r (ok if it copies garbage after r)
822 for (int i = 0; i < _relocbuf_size; i++) {
823 _relocbuf[i] = ((void**)r)[i];
824 }
825}
826
827relocInfo::relocType RelocationHolder::type() const {
828 return reloc()->type();
829}
830
831// A DataRelocation always points at a memory or load-constant instruction..
832// It is absolute on most machines, and the constant is split on RISCs.
833// The specific subtypes are oop, external_word, and internal_word.
834// By convention, the "value" does not include a separately reckoned "offset".
835class DataRelocation : public Relocation {
836 public:
837 DataRelocation(relocInfo::relocType type) : Relocation(type) {}
838
839 bool is_data() { return true; }
840
841 // both target and offset must be computed somehow from relocation data
842 virtual int offset() { return 0; }
843 address value() = 0;
844 void set_value(address x) { set_value(x, offset()); }
845 void set_value(address x, intptr_t o) {
846 if (addr_in_const())
847 const_set_data_value(x);
848 else
849 pd_set_data_value(x, o);
850 }
851 void verify_value(address x) {
852 if (addr_in_const())
853 const_verify_data_value(x);
854 else
855 pd_verify_data_value(x, offset());
856 }
857
858 // The "o" (displacement) argument is relevant only to split relocations
859 // on RISC machines. In some CPUs (SPARC), the set-hi and set-lo ins'ns
860 // can encode more than 32 bits between them. This allows compilers to
861 // share set-hi instructions between addresses that differ by a small
862 // offset (e.g., different static variables in the same class).
863 // On such machines, the "x" argument to set_value on all set-lo
864 // instructions must be the same as the "x" argument for the
865 // corresponding set-hi instructions. The "o" arguments for the
866 // set-hi instructions are ignored, and must not affect the high-half
867 // immediate constant. The "o" arguments for the set-lo instructions are
868 // added into the low-half immediate constant, and must not overflow it.
869};
870
871// A CallRelocation always points at a call instruction.
872// It is PC-relative on most machines.
873class CallRelocation : public Relocation {
874 public:
875 CallRelocation(relocInfo::relocType type) : Relocation(type) { }
876
877 bool is_call() { return true; }
878
879 address destination() { return pd_call_destination(); }
880 void set_destination(address x); // pd_set_call_destination
881
882 void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest);
883 address value() { return destination(); }
884 void set_value(address x) { set_destination(x); }
885};
886
887class oop_Relocation : public DataRelocation {
888 public:
889 // encode in one of these formats: [] [n] [n l] [Nn l] [Nn Ll]
890 // an oop in the CodeBlob's oop pool
891 static RelocationHolder spec(int oop_index, int offset = 0) {
892 assert(oop_index > 0, "must be a pool-resident oop")do { if (!(oop_index > 0)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 892, "assert(" "oop_index > 0" ") failed", "must be a pool-resident oop"
); ::breakpoint(); } } while (0)
;
893 RelocationHolder rh = newHolder();
894 new(rh) oop_Relocation(oop_index, offset);
895 return rh;
896 }
897 // an oop in the instruction stream
898 static RelocationHolder spec_for_immediate() {
899 // If no immediate oops are generated, we can skip some walks over nmethods.
900 // Assert that they don't get generated accidently!
901 assert(relocInfo::mustIterateImmediateOopsInCode(),do { if (!(relocInfo::mustIterateImmediateOopsInCode())) { (*
g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 902, "assert(" "relocInfo::mustIterateImmediateOopsInCode()"
") failed", "Must return true so we will search for oops as roots etc. in the code."
); ::breakpoint(); } } while (0)
902 "Must return true so we will search for oops as roots etc. in the code.")do { if (!(relocInfo::mustIterateImmediateOopsInCode())) { (*
g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 902, "assert(" "relocInfo::mustIterateImmediateOopsInCode()"
") failed", "Must return true so we will search for oops as roots etc. in the code."
); ::breakpoint(); } } while (0)
;
903 const int oop_index = 0;
904 const int offset = 0; // if you want an offset, use the oop pool
905 RelocationHolder rh = newHolder();
906 new(rh) oop_Relocation(oop_index, offset);
907 return rh;
908 }
909
910 private:
911 jint _oop_index; // if > 0, index into CodeBlob::oop_at
912 jint _offset; // byte offset to apply to the oop itself
913
914 oop_Relocation(int oop_index, int offset)
915 : DataRelocation(relocInfo::oop_type), _oop_index(oop_index), _offset(offset) { }
916
917 friend class RelocIterator;
918 oop_Relocation() : DataRelocation(relocInfo::oop_type) {}
919
920 public:
921 int oop_index() { return _oop_index; }
922 int offset() { return _offset; }
923
924 // data is packed in "2_ints" format: [i o] or [Ii Oo]
925 void pack_data_to(CodeSection* dest);
926 void unpack_data();
927
928 void fix_oop_relocation(); // reasserts oop value
929
930 void verify_oop_relocation();
931
932 address value() { return cast_from_oop<address>(*oop_addr()); }
933
934 bool oop_is_immediate() { return oop_index() == 0; }
935
936 oop* oop_addr(); // addr or &pool[jint_data]
937 oop oop_value(); // *oop_addr
938 // Note: oop_value transparently converts Universe::non_oop_word to NULL.
939};
940
941
942// copy of oop_Relocation for now but may delete stuff in both/either
943class metadata_Relocation : public DataRelocation {
944
945 public:
946 // encode in one of these formats: [] [n] [n l] [Nn l] [Nn Ll]
947 // an metadata in the CodeBlob's metadata pool
948 static RelocationHolder spec(int metadata_index, int offset = 0) {
949 assert(metadata_index > 0, "must be a pool-resident metadata")do { if (!(metadata_index > 0)) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 949, "assert(" "metadata_index > 0" ") failed", "must be a pool-resident metadata"
); ::breakpoint(); } } while (0)
;
950 RelocationHolder rh = newHolder();
951 new(rh) metadata_Relocation(metadata_index, offset);
952 return rh;
953 }
954 // an metadata in the instruction stream
955 static RelocationHolder spec_for_immediate() {
956 const int metadata_index = 0;
957 const int offset = 0; // if you want an offset, use the metadata pool
958 RelocationHolder rh = newHolder();
959 new(rh) metadata_Relocation(metadata_index, offset);
960 return rh;
961 }
962
963 private:
964 jint _metadata_index; // if > 0, index into nmethod::metadata_at
965 jint _offset; // byte offset to apply to the metadata itself
966
967 metadata_Relocation(int metadata_index, int offset)
968 : DataRelocation(relocInfo::metadata_type), _metadata_index(metadata_index), _offset(offset) { }
969
970 friend class RelocIterator;
971 metadata_Relocation() : DataRelocation(relocInfo::metadata_type) { }
972
973 // Fixes a Metadata pointer in the code. Most platforms embeds the
974 // Metadata pointer in the code at compile time so this is empty
975 // for them.
976 void pd_fix_value(address x);
977
978 public:
979 int metadata_index() { return _metadata_index; }
980 int offset() { return _offset; }
981
982 // data is packed in "2_ints" format: [i o] or [Ii Oo]
983 void pack_data_to(CodeSection* dest);
984 void unpack_data();
985
986 void fix_metadata_relocation(); // reasserts metadata value
987
988 address value() { return (address) *metadata_addr(); }
989
990 bool metadata_is_immediate() { return metadata_index() == 0; }
991
992 Metadata** metadata_addr(); // addr or &pool[jint_data]
993 Metadata* metadata_value(); // *metadata_addr
994 // Note: metadata_value transparently converts Universe::non_metadata_word to NULL.
995};
996
997
998class virtual_call_Relocation : public CallRelocation {
999
1000 public:
1001 // "cached_value" points to the first associated set-oop.
1002 // The oop_limit helps find the last associated set-oop.
1003 // (See comments at the top of this file.)
1004 static RelocationHolder spec(address cached_value, jint method_index = 0) {
1005 RelocationHolder rh = newHolder();
1006 new(rh) virtual_call_Relocation(cached_value, method_index);
1007 return rh;
1008 }
1009
1010 private:
1011 address _cached_value; // location of set-value instruction
1012 jint _method_index; // resolved method for a Java call
1013
1014 virtual_call_Relocation(address cached_value, int method_index)
1015 : CallRelocation(relocInfo::virtual_call_type),
1016 _cached_value(cached_value),
1017 _method_index(method_index) {
1018 assert(cached_value != NULL, "first oop address must be specified")do { if (!(cached_value != __null)) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 1018, "assert(" "cached_value != __null" ") failed", "first oop address must be specified"
); ::breakpoint(); } } while (0)
;
1019 }
1020
1021 friend class RelocIterator;
1022 virtual_call_Relocation() : CallRelocation(relocInfo::virtual_call_type) { }
1023
1024 public:
1025 address cached_value();
1026
1027 int method_index() { return _method_index; }
1028 Method* method_value();
1029
1030 // data is packed as scaled offsets in "2_ints" format: [f l] or [Ff Ll]
1031 // oop_limit is set to 0 if the limit falls somewhere within the call.
1032 // When unpacking, a zero oop_limit is taken to refer to the end of the call.
1033 // (This has the effect of bringing in the call's delay slot on SPARC.)
1034 void pack_data_to(CodeSection* dest);
1035 void unpack_data();
1036
1037 bool clear_inline_cache();
1038};
1039
1040
1041class opt_virtual_call_Relocation : public CallRelocation {
1042 public:
1043 static RelocationHolder spec(int method_index = 0) {
1044 RelocationHolder rh = newHolder();
1045 new(rh) opt_virtual_call_Relocation(method_index);
1046 return rh;
1047 }
1048
1049 private:
1050 jint _method_index; // resolved method for a Java call
1051
1052 opt_virtual_call_Relocation(int method_index)
1053 : CallRelocation(relocInfo::opt_virtual_call_type),
1054 _method_index(method_index) { }
1055
1056 friend class RelocIterator;
1057 opt_virtual_call_Relocation() : CallRelocation(relocInfo::opt_virtual_call_type) {}
1058
1059 public:
1060 int method_index() { return _method_index; }
1061 Method* method_value();
1062
1063 void pack_data_to(CodeSection* dest);
1064 void unpack_data();
1065
1066 bool clear_inline_cache();
1067
1068 // find the matching static_stub
1069 address static_stub();
1070};
1071
1072
1073class static_call_Relocation : public CallRelocation {
1074 public:
1075 static RelocationHolder spec(int method_index = 0) {
1076 RelocationHolder rh = newHolder();
1077 new(rh) static_call_Relocation(method_index);
1078 return rh;
1079 }
1080
1081 private:
1082 jint _method_index; // resolved method for a Java call
1083
1084 static_call_Relocation(int method_index)
1085 : CallRelocation(relocInfo::static_call_type),
1086 _method_index(method_index) { }
1087
1088 friend class RelocIterator;
1089 static_call_Relocation() : CallRelocation(relocInfo::static_call_type) {}
1090
1091 public:
1092 int method_index() { return _method_index; }
1093 Method* method_value();
1094
1095 void pack_data_to(CodeSection* dest);
1096 void unpack_data();
1097
1098 bool clear_inline_cache();
1099
1100 // find the matching static_stub
1101 address static_stub();
1102};
1103
1104class static_stub_Relocation : public Relocation {
1105 public:
1106 static RelocationHolder spec(address static_call) {
1107 RelocationHolder rh = newHolder();
1108 new(rh) static_stub_Relocation(static_call);
1109 return rh;
1110 }
1111
1112 private:
1113 address _static_call; // location of corresponding static_call
1114
1115 static_stub_Relocation(address static_call)
1116 : Relocation(relocInfo::static_stub_type),
1117 _static_call(static_call) { }
1118
1119 friend class RelocIterator;
1120 static_stub_Relocation() : Relocation(relocInfo::static_stub_type) { }
1121
1122 public:
1123 bool clear_inline_cache();
1124
1125 address static_call() { return _static_call; }
1126
1127 // data is packed as a scaled offset in "1_int" format: [c] or [Cc]
1128 void pack_data_to(CodeSection* dest);
1129 void unpack_data();
1130};
1131
1132class runtime_call_Relocation : public CallRelocation {
1133
1134 public:
1135 static RelocationHolder spec() {
1136 RelocationHolder rh = newHolder();
1137 new(rh) runtime_call_Relocation();
1138 return rh;
1139 }
1140
1141 private:
1142 friend class RelocIterator;
1143 runtime_call_Relocation() : CallRelocation(relocInfo::runtime_call_type) { }
1144
1145 public:
1146};
1147
1148
1149class runtime_call_w_cp_Relocation : public CallRelocation {
1150 public:
1151 static RelocationHolder spec() {
1152 RelocationHolder rh = newHolder();
1153 new(rh) runtime_call_w_cp_Relocation();
1154 return rh;
1155 }
1156
1157 private:
1158 friend class RelocIterator;
1159 runtime_call_w_cp_Relocation()
1160 : CallRelocation(relocInfo::runtime_call_w_cp_type),
1161 _offset(-4) /* <0 = invalid */ { }
1162
1163 // On z/Architecture, runtime calls are either a sequence
1164 // of two instructions (load destination of call from constant pool + do call)
1165 // or a pc-relative call. The pc-relative call is faster, but it can only
1166 // be used if the destination of the call is not too far away.
1167 // In order to be able to patch a pc-relative call back into one using
1168 // the constant pool, we have to remember the location of the call's destination
1169 // in the constant pool.
1170 int _offset;
1171
1172 public:
1173 void set_constant_pool_offset(int offset) { _offset = offset; }
1174 int get_constant_pool_offset() { return _offset; }
1175 void pack_data_to(CodeSection * dest);
1176 void unpack_data();
1177};
1178
1179// Trampoline Relocations.
1180// A trampoline allows to encode a small branch in the code, even if there
1181// is the chance that this branch can not reach all possible code locations.
1182// If the relocation finds that a branch is too far for the instruction
1183// in the code, it can patch it to jump to the trampoline where is
1184// sufficient space for a far branch. Needed on PPC.
1185class trampoline_stub_Relocation : public Relocation {
1186 public:
1187 static RelocationHolder spec(address static_call) {
1188 RelocationHolder rh = newHolder();
1189 return (new (rh) trampoline_stub_Relocation(static_call));
1190 }
1191
1192 private:
1193 address _owner; // Address of the NativeCall that owns the trampoline.
1194
1195 trampoline_stub_Relocation(address owner)
1196 : Relocation(relocInfo::trampoline_stub_type),
1197 _owner(owner) { }
1198
1199 friend class RelocIterator;
1200 trampoline_stub_Relocation() : Relocation(relocInfo::trampoline_stub_type) { }
1201
1202 public:
1203
1204 // Return the address of the NativeCall that owns the trampoline.
1205 address owner() { return _owner; }
1206
1207 void pack_data_to(CodeSection * dest);
1208 void unpack_data();
1209
1210 // Find the trampoline stub for a call.
1211 static address get_trampoline_for(address call, nmethod* code);
1212};
1213
1214class external_word_Relocation : public DataRelocation {
1215 public:
1216 static RelocationHolder spec(address target) {
1217 assert(target != NULL, "must not be null")do { if (!(target != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 1217, "assert(" "target != __null" ") failed", "must not be null"
); ::breakpoint(); } } while (0)
;
1218 RelocationHolder rh = newHolder();
1219 new(rh) external_word_Relocation(target);
1220 return rh;
1221 }
1222
1223 // Use this one where all 32/64 bits of the target live in the code stream.
1224 // The target must be an intptr_t, and must be absolute (not relative).
1225 static RelocationHolder spec_for_immediate() {
1226 RelocationHolder rh = newHolder();
1227 new(rh) external_word_Relocation(NULL__null);
1228 return rh;
1229 }
1230
1231 // Some address looking values aren't safe to treat as relocations
1232 // and should just be treated as constants.
1233 static bool can_be_relocated(address target) {
1234 assert(target == NULL || (uintptr_t)target >= (uintptr_t)os::vm_page_size(), INTPTR_FORMAT, (intptr_t)target)do { if (!(target == __null || (uintptr_t)target >= (uintptr_t
)os::vm_page_size())) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 1234, "assert(" "target == __null || (uintptr_t)target >= (uintptr_t)os::vm_page_size()"
") failed", "0x%016" "l" "x", (intptr_t)target); ::breakpoint
(); } } while (0)
;
1235 return target != NULL__null;
1236 }
1237
1238 private:
1239 address _target; // address in runtime
1240
1241 external_word_Relocation(address target)
1242 : DataRelocation(relocInfo::external_word_type), _target(target) { }
1243
1244 friend class RelocIterator;
1245 external_word_Relocation() : DataRelocation(relocInfo::external_word_type) { }
1246
1247 public:
1248 // data is packed as a well-known address in "1_int" format: [a] or [Aa]
1249 // The function runtime_address_to_index is used to turn full addresses
1250 // to short indexes, if they are pre-registered by the stub mechanism.
1251 // If the "a" value is 0 (i.e., _target is NULL), the address is stored
1252 // in the code stream. See external_word_Relocation::target().
1253 void pack_data_to(CodeSection* dest);
1254 void unpack_data();
1255
1256 void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest);
1257 address target(); // if _target==NULL, fetch addr from code stream
1258 address value() { return target(); }
1259};
1260
1261class internal_word_Relocation : public DataRelocation {
1262
1263 public:
1264 static RelocationHolder spec(address target) {
1265 assert(target != NULL, "must not be null")do { if (!(target != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 1265, "assert(" "target != __null" ") failed", "must not be null"
); ::breakpoint(); } } while (0)
;
1266 RelocationHolder rh = newHolder();
1267 new(rh) internal_word_Relocation(target);
1268 return rh;
1269 }
1270
1271 // use this one where all the bits of the target can fit in the code stream:
1272 static RelocationHolder spec_for_immediate() {
1273 RelocationHolder rh = newHolder();
1274 new(rh) internal_word_Relocation(NULL__null);
1275 return rh;
1276 }
1277
1278 // default section -1 means self-relative
1279 internal_word_Relocation(address target, int section = -1,
1280 relocInfo::relocType type = relocInfo::internal_word_type)
1281 : DataRelocation(type), _target(target), _section(section) { }
1282
1283 protected:
1284 address _target; // address in CodeBlob
1285 int _section; // section providing base address, if any
1286
1287 friend class RelocIterator;
1288 internal_word_Relocation(relocInfo::relocType type = relocInfo::internal_word_type)
1289 : DataRelocation(type) { }
1290
1291 // bit-width of LSB field in packed offset, if section >= 0
1292 enum { section_width = 2 }; // must equal CodeBuffer::sect_bits
1293
1294 public:
1295 // data is packed as a scaled offset in "1_int" format: [o] or [Oo]
1296 // If the "o" value is 0 (i.e., _target is NULL), the offset is stored
1297 // in the code stream. See internal_word_Relocation::target().
1298 // If _section is not -1, it is appended to the low bits of the offset.
1299 void pack_data_to(CodeSection* dest);
1300 void unpack_data();
1301
1302 void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest);
1303 address target(); // if _target==NULL, fetch addr from code stream
1304 int section() { return _section; }
1305 address value() { return target(); }
1306};
1307
1308class section_word_Relocation : public internal_word_Relocation {
1309 public:
1310 static RelocationHolder spec(address target, int section) {
1311 RelocationHolder rh = newHolder();
1312 new(rh) section_word_Relocation(target, section);
1313 return rh;
1314 }
1315
1316 section_word_Relocation(address target, int section)
1317 : internal_word_Relocation(target, section, relocInfo::section_word_type) {
1318 assert(target != NULL, "must not be null")do { if (!(target != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 1318, "assert(" "target != __null" ") failed", "must not be null"
); ::breakpoint(); } } while (0)
;
1319 assert(section >= 0 && section < RelocIterator::SECT_LIMIT, "must be a valid section")do { if (!(section >= 0 && section < RelocIterator
::SECT_LIMIT)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 1319, "assert(" "section >= 0 && section < RelocIterator::SECT_LIMIT"
") failed", "must be a valid section"); ::breakpoint(); } } while
(0)
;
1320 }
1321
1322 //void pack_data_to -- inherited
1323 void unpack_data();
1324
1325 private:
1326 friend class RelocIterator;
1327 section_word_Relocation() : internal_word_Relocation(relocInfo::section_word_type) { }
1328};
1329
1330
1331class poll_Relocation : public Relocation {
1332 bool is_data() { return true; }
1333 void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest);
1334 public:
1335 poll_Relocation(relocInfo::relocType type = relocInfo::poll_type) : Relocation(type) { }
1336};
1337
1338class poll_return_Relocation : public poll_Relocation {
1339 public:
1340 poll_return_Relocation() : poll_Relocation(relocInfo::relocInfo::poll_return_type) { }
1341};
1342
1343// We know all the xxx_Relocation classes, so now we can define these:
1344#define EACH_CASE(name) \
1345inline name##_Relocation* RelocIterator::name##_reloc() { \
1346 assert(type() == relocInfo::name##_type, "type must agree")do { if (!(type() == relocInfo::name##_type)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/code/relocInfo.hpp"
, 1346, "assert(" "type() == relocInfo::name##_type" ") failed"
, "type must agree"); ::breakpoint(); } } while (0)
; \
1347 /* The purpose of the placed "new" is to re-use the same */ \
1348 /* stack storage for each new iteration. */ \
1349 name##_Relocation* r = new(_rh) name##_Relocation(); \
1350 r->set_binding(this); \
1351 r->name##_Relocation::unpack_data(); \
1352 return r; \
1353}
1354APPLY_TO_RELOCATIONS(EACH_CASE)EACH_CASE(oop) EACH_CASE(metadata) EACH_CASE(virtual_call) EACH_CASE
(opt_virtual_call) EACH_CASE(static_call) EACH_CASE(static_stub
) EACH_CASE(runtime_call) EACH_CASE(runtime_call_w_cp) EACH_CASE
(external_word) EACH_CASE(internal_word) EACH_CASE(poll) EACH_CASE
(poll_return) EACH_CASE(section_word) EACH_CASE(trampoline_stub
)
;
1355#undef EACH_CASE
1356
1357inline RelocIterator::RelocIterator(CompiledMethod* nm, address begin, address limit) {
1358 initialize(nm, begin, limit);
1359}
1360
1361#endif // SHARE_CODE_RELOCINFO_HPP