File: | jdk/src/hotspot/share/cds/archiveBuilder.cpp |
Warning: | line 1193, column 13 Value stored to 'top' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * Copyright (c) 2020, 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 "cds/archiveBuilder.hpp" |
27 | #include "cds/archiveUtils.hpp" |
28 | #include "cds/cppVtables.hpp" |
29 | #include "cds/dumpAllocStats.hpp" |
30 | #include "cds/metaspaceShared.hpp" |
31 | #include "classfile/classLoaderDataShared.hpp" |
32 | #include "classfile/symbolTable.hpp" |
33 | #include "classfile/systemDictionaryShared.hpp" |
34 | #include "classfile/vmClasses.hpp" |
35 | #include "interpreter/abstractInterpreter.hpp" |
36 | #include "logging/log.hpp" |
37 | #include "logging/logStream.hpp" |
38 | #include "memory/allStatic.hpp" |
39 | #include "memory/memRegion.hpp" |
40 | #include "memory/resourceArea.hpp" |
41 | #include "oops/instanceKlass.hpp" |
42 | #include "oops/objArrayKlass.hpp" |
43 | #include "oops/oopHandle.inline.hpp" |
44 | #include "runtime/arguments.hpp" |
45 | #include "runtime/globals_extension.hpp" |
46 | #include "runtime/sharedRuntime.hpp" |
47 | #include "runtime/thread.hpp" |
48 | #include "utilities/align.hpp" |
49 | #include "utilities/bitMap.inline.hpp" |
50 | #include "utilities/formatBuffer.hpp" |
51 | #include "utilities/hashtable.inline.hpp" |
52 | |
53 | ArchiveBuilder* ArchiveBuilder::_current = NULL__null; |
54 | |
55 | ArchiveBuilder::OtherROAllocMark::~OtherROAllocMark() { |
56 | char* newtop = ArchiveBuilder::current()->_ro_region.top(); |
57 | ArchiveBuilder::alloc_stats()->record_other_type(int(newtop - _oldtop), true); |
58 | } |
59 | |
60 | ArchiveBuilder::SourceObjList::SourceObjList() : _ptrmap(16 * K) { |
61 | _total_bytes = 0; |
62 | _objs = new (ResourceObj::C_HEAP, mtClassShared) GrowableArray<SourceObjInfo*>(128 * K, mtClassShared); |
63 | } |
64 | |
65 | ArchiveBuilder::SourceObjList::~SourceObjList() { |
66 | delete _objs; |
67 | } |
68 | |
69 | void ArchiveBuilder::SourceObjList::append(MetaspaceClosure::Ref* enclosing_ref, SourceObjInfo* src_info) { |
70 | // Save this source object for copying |
71 | _objs->append(src_info); |
72 | |
73 | // Prepare for marking the pointers in this source object |
74 | assert(is_aligned(_total_bytes, sizeof(address)), "must be")do { if (!(is_aligned(_total_bytes, sizeof(address)))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 74, "assert(" "is_aligned(_total_bytes, sizeof(address))" ") failed" , "must be"); ::breakpoint(); } } while (0); |
75 | src_info->set_ptrmap_start(_total_bytes / sizeof(address)); |
76 | _total_bytes = align_up(_total_bytes + (uintx)src_info->size_in_bytes(), sizeof(address)); |
77 | src_info->set_ptrmap_end(_total_bytes / sizeof(address)); |
78 | |
79 | BitMap::idx_t bitmap_size_needed = BitMap::idx_t(src_info->ptrmap_end()); |
80 | if (_ptrmap.size() <= bitmap_size_needed) { |
81 | _ptrmap.resize((bitmap_size_needed + 1) * 2); |
82 | } |
83 | } |
84 | |
85 | void ArchiveBuilder::SourceObjList::remember_embedded_pointer(SourceObjInfo* src_info, MetaspaceClosure::Ref* ref) { |
86 | // src_obj contains a pointer. Remember the location of this pointer in _ptrmap, |
87 | // so that we can copy/relocate it later. E.g., if we have |
88 | // class Foo { intx scala; Bar* ptr; } |
89 | // Foo *f = 0x100; |
90 | // To mark the f->ptr pointer on 64-bit platform, this function is called with |
91 | // src_info()->obj() == 0x100 |
92 | // ref->addr() == 0x108 |
93 | address src_obj = src_info->obj(); |
94 | address* field_addr = ref->addr(); |
95 | assert(src_info->ptrmap_start() < _total_bytes, "sanity")do { if (!(src_info->ptrmap_start() < _total_bytes)) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 95, "assert(" "src_info->ptrmap_start() < _total_bytes" ") failed", "sanity"); ::breakpoint(); } } while (0); |
96 | assert(src_info->ptrmap_end() <= _total_bytes, "sanity")do { if (!(src_info->ptrmap_end() <= _total_bytes)) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 96, "assert(" "src_info->ptrmap_end() <= _total_bytes" ") failed", "sanity"); ::breakpoint(); } } while (0); |
97 | assert(*field_addr != NULL, "should have checked")do { if (!(*field_addr != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 97, "assert(" "*field_addr != __null" ") failed", "should have checked" ); ::breakpoint(); } } while (0); |
98 | |
99 | intx field_offset_in_bytes = ((address)field_addr) - src_obj; |
100 | DEBUG_ONLY(int src_obj_size = src_info->size_in_bytes();)int src_obj_size = src_info->size_in_bytes(); |
101 | assert(field_offset_in_bytes >= 0, "must be")do { if (!(field_offset_in_bytes >= 0)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 101, "assert(" "field_offset_in_bytes >= 0" ") failed", "must be" ); ::breakpoint(); } } while (0); |
102 | assert(field_offset_in_bytes + intx(sizeof(intptr_t)) <= intx(src_obj_size), "must be")do { if (!(field_offset_in_bytes + intx(sizeof(intptr_t)) <= intx(src_obj_size))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 102, "assert(" "field_offset_in_bytes + intx(sizeof(intptr_t)) <= intx(src_obj_size)" ") failed", "must be"); ::breakpoint(); } } while (0); |
103 | assert(is_aligned(field_offset_in_bytes, sizeof(address)), "must be")do { if (!(is_aligned(field_offset_in_bytes, sizeof(address)) )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 103, "assert(" "is_aligned(field_offset_in_bytes, sizeof(address))" ") failed", "must be"); ::breakpoint(); } } while (0); |
104 | |
105 | BitMap::idx_t idx = BitMap::idx_t(src_info->ptrmap_start() + (uintx)(field_offset_in_bytes / sizeof(address))); |
106 | _ptrmap.set_bit(BitMap::idx_t(idx)); |
107 | } |
108 | |
109 | class RelocateEmbeddedPointers : public BitMapClosure { |
110 | ArchiveBuilder* _builder; |
111 | address _dumped_obj; |
112 | BitMap::idx_t _start_idx; |
113 | public: |
114 | RelocateEmbeddedPointers(ArchiveBuilder* builder, address dumped_obj, BitMap::idx_t start_idx) : |
115 | _builder(builder), _dumped_obj(dumped_obj), _start_idx(start_idx) {} |
116 | |
117 | bool do_bit(BitMap::idx_t bit_offset) { |
118 | size_t field_offset = size_t(bit_offset - _start_idx) * sizeof(address); |
119 | address* ptr_loc = (address*)(_dumped_obj + field_offset); |
120 | |
121 | address old_p = *ptr_loc; |
122 | address new_p = _builder->get_dumped_addr(old_p); |
123 | |
124 | log_trace(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Trace))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Trace>("Ref: [" PTR_FORMAT"0x%016" "l" "x" "] -> " PTR_FORMAT"0x%016" "l" "x" " => " PTR_FORMAT"0x%016" "l" "x", |
125 | p2i(ptr_loc), p2i(old_p), p2i(new_p)); |
126 | |
127 | ArchivePtrMarker::set_and_mark_pointer(ptr_loc, new_p); |
128 | return true; // keep iterating the bitmap |
129 | } |
130 | }; |
131 | |
132 | void ArchiveBuilder::SourceObjList::relocate(int i, ArchiveBuilder* builder) { |
133 | SourceObjInfo* src_info = objs()->at(i); |
134 | assert(src_info->should_copy(), "must be")do { if (!(src_info->should_copy())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 134, "assert(" "src_info->should_copy()" ") failed", "must be" ); ::breakpoint(); } } while (0); |
135 | BitMap::idx_t start = BitMap::idx_t(src_info->ptrmap_start()); // inclusive |
136 | BitMap::idx_t end = BitMap::idx_t(src_info->ptrmap_end()); // exclusive |
137 | |
138 | RelocateEmbeddedPointers relocator(builder, src_info->dumped_addr(), start); |
139 | _ptrmap.iterate(&relocator, start, end); |
140 | } |
141 | |
142 | ArchiveBuilder::ArchiveBuilder() : |
143 | _current_dump_space(NULL__null), |
144 | _buffer_bottom(NULL__null), |
145 | _last_verified_top(NULL__null), |
146 | _num_dump_regions_used(0), |
147 | _other_region_used_bytes(0), |
148 | _requested_static_archive_bottom(NULL__null), |
149 | _requested_static_archive_top(NULL__null), |
150 | _requested_dynamic_archive_bottom(NULL__null), |
151 | _requested_dynamic_archive_top(NULL__null), |
152 | _mapped_static_archive_bottom(NULL__null), |
153 | _mapped_static_archive_top(NULL__null), |
154 | _buffer_to_requested_delta(0), |
155 | _rw_region("rw", MAX_SHARED_DELTA), |
156 | _ro_region("ro", MAX_SHARED_DELTA), |
157 | _rw_src_objs(), |
158 | _ro_src_objs(), |
159 | _src_obj_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE), |
160 | _total_closed_heap_region_size(0), |
161 | _total_open_heap_region_size(0), |
162 | _estimated_metaspaceobj_bytes(0), |
163 | _estimated_hashtable_bytes(0) |
164 | { |
165 | _klasses = new (ResourceObj::C_HEAP, mtClassShared) GrowableArray<Klass*>(4 * K, mtClassShared); |
166 | _symbols = new (ResourceObj::C_HEAP, mtClassShared) GrowableArray<Symbol*>(256 * K, mtClassShared); |
167 | _special_refs = new (ResourceObj::C_HEAP, mtClassShared) GrowableArray<SpecialRefInfo>(24 * K, mtClassShared); |
168 | |
169 | assert(_current == NULL, "must be")do { if (!(_current == __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 169, "assert(" "_current == __null" ") failed", "must be"); ::breakpoint(); } } while (0); |
170 | _current = this; |
171 | } |
172 | |
173 | ArchiveBuilder::~ArchiveBuilder() { |
174 | assert(_current == this, "must be")do { if (!(_current == this)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 174, "assert(" "_current == this" ") failed", "must be"); :: breakpoint(); } } while (0); |
175 | _current = NULL__null; |
176 | |
177 | clean_up_src_obj_table(); |
178 | |
179 | for (int i = 0; i < _symbols->length(); i++) { |
180 | _symbols->at(i)->decrement_refcount(); |
181 | } |
182 | |
183 | delete _klasses; |
184 | delete _symbols; |
185 | delete _special_refs; |
186 | if (_shared_rs.is_reserved()) { |
187 | _shared_rs.release(); |
188 | } |
189 | } |
190 | |
191 | bool ArchiveBuilder::is_dumping_full_module_graph() { |
192 | return DumpSharedSpaces && MetaspaceShared::use_full_module_graph(); |
193 | } |
194 | |
195 | class GatherKlassesAndSymbols : public UniqueMetaspaceClosure { |
196 | ArchiveBuilder* _builder; |
197 | |
198 | public: |
199 | GatherKlassesAndSymbols(ArchiveBuilder* builder) : _builder(builder) {} |
200 | |
201 | virtual bool do_unique_ref(Ref* ref, bool read_only) { |
202 | return _builder->gather_klass_and_symbol(ref, read_only); |
203 | } |
204 | }; |
205 | |
206 | bool ArchiveBuilder::gather_klass_and_symbol(MetaspaceClosure::Ref* ref, bool read_only) { |
207 | if (ref->obj() == NULL__null) { |
208 | return false; |
209 | } |
210 | if (get_follow_mode(ref) != make_a_copy) { |
211 | return false; |
212 | } |
213 | if (ref->msotype() == MetaspaceObj::ClassType) { |
214 | Klass* klass = (Klass*)ref->obj(); |
215 | assert(klass->is_klass(), "must be")do { if (!(klass->is_klass())) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 215, "assert(" "klass->is_klass()" ") failed", "must be" ); ::breakpoint(); } } while (0); |
216 | if (!is_excluded(klass)) { |
217 | _klasses->append(klass); |
218 | } |
219 | // See RunTimeClassInfo::get_for() |
220 | _estimated_metaspaceobj_bytes += align_up(BytesPerWord, SharedSpaceObjectAlignment); |
221 | } else if (ref->msotype() == MetaspaceObj::SymbolType) { |
222 | // Make sure the symbol won't be GC'ed while we are dumping the archive. |
223 | Symbol* sym = (Symbol*)ref->obj(); |
224 | sym->increment_refcount(); |
225 | _symbols->append(sym); |
226 | } |
227 | |
228 | int bytes = ref->size() * BytesPerWord; |
229 | _estimated_metaspaceobj_bytes += align_up(bytes, SharedSpaceObjectAlignment); |
230 | |
231 | return true; // recurse |
232 | } |
233 | |
234 | void ArchiveBuilder::gather_klasses_and_symbols() { |
235 | ResourceMark rm; |
236 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>("Gathering classes and symbols ... "); |
237 | GatherKlassesAndSymbols doit(this); |
238 | iterate_roots(&doit, /*is_relocating_pointers=*/false); |
239 | #if INCLUDE_CDS_JAVA_HEAP1 |
240 | if (is_dumping_full_module_graph()) { |
241 | ClassLoaderDataShared::iterate_symbols(&doit); |
242 | } |
243 | #endif |
244 | doit.finish(); |
245 | |
246 | if (DumpSharedSpaces) { |
247 | // To ensure deterministic contents in the static archive, we need to ensure that |
248 | // we iterate the MetaspaceObjs in a deterministic order. It doesn't matter where |
249 | // the MetaspaceObjs are located originally, as they are copied sequentially into |
250 | // the archive during the iteration. |
251 | // |
252 | // The only issue here is that the symbol table and the system directories may be |
253 | // randomly ordered, so we copy the symbols and klasses into two arrays and sort |
254 | // them deterministically. |
255 | // |
256 | // During -Xshare:dump, the order of Symbol creation is strictly determined by |
257 | // the SharedClassListFile (class loading is done in a single thread and the JIT |
258 | // is disabled). Also, Symbols are allocated in monotonically increasing addresses |
259 | // (see Symbol::operator new(size_t, int)). So if we iterate the Symbols by |
260 | // ascending address order, we ensure that all Symbols are copied into deterministic |
261 | // locations in the archive. |
262 | // |
263 | // TODO: in the future, if we want to produce deterministic contents in the |
264 | // dynamic archive, we might need to sort the symbols alphabetically (also see |
265 | // DynamicArchiveBuilder::sort_methods()). |
266 | sort_symbols_and_fix_hash(); |
267 | sort_klasses(); |
268 | |
269 | // TODO -- we need a proper estimate for the archived modules, etc, |
270 | // but this should be enough for now |
271 | _estimated_metaspaceobj_bytes += 200 * 1024 * 1024; |
272 | } |
273 | } |
274 | |
275 | int ArchiveBuilder::compare_symbols_by_address(Symbol** a, Symbol** b) { |
276 | if (a[0] < b[0]) { |
277 | return -1; |
278 | } else { |
279 | assert(a[0] > b[0], "Duplicated symbol %s unexpected", (*a)->as_C_string())do { if (!(a[0] > b[0])) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 279, "assert(" "a[0] > b[0]" ") failed", "Duplicated symbol %s unexpected" , (*a)->as_C_string()); ::breakpoint(); } } while (0); |
280 | return 1; |
281 | } |
282 | } |
283 | |
284 | void ArchiveBuilder::sort_symbols_and_fix_hash() { |
285 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>("Sorting symbols and fixing identity hash ... "); |
286 | os::init_random(0x12345678); |
287 | _symbols->sort(compare_symbols_by_address); |
288 | for (int i = 0; i < _symbols->length(); i++) { |
289 | assert(_symbols->at(i)->is_permanent(), "archived symbols must be permanent")do { if (!(_symbols->at(i)->is_permanent())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 289, "assert(" "_symbols->at(i)->is_permanent()" ") failed" , "archived symbols must be permanent"); ::breakpoint(); } } while (0); |
290 | _symbols->at(i)->update_identity_hash(); |
291 | } |
292 | } |
293 | |
294 | int ArchiveBuilder::compare_klass_by_name(Klass** a, Klass** b) { |
295 | return a[0]->name()->fast_compare(b[0]->name()); |
296 | } |
297 | |
298 | void ArchiveBuilder::sort_klasses() { |
299 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>("Sorting classes ... "); |
300 | _klasses->sort(compare_klass_by_name); |
301 | } |
302 | |
303 | size_t ArchiveBuilder::estimate_archive_size() { |
304 | // size of the symbol table and two dictionaries, plus the RunTimeClassInfo's |
305 | size_t symbol_table_est = SymbolTable::estimate_size_for_archive(); |
306 | size_t dictionary_est = SystemDictionaryShared::estimate_size_for_archive(); |
307 | _estimated_hashtable_bytes = symbol_table_est + dictionary_est; |
308 | |
309 | size_t total = 0; |
310 | |
311 | total += _estimated_metaspaceobj_bytes; |
312 | total += _estimated_hashtable_bytes; |
313 | |
314 | // allow fragmentation at the end of each dump region |
315 | total += _total_dump_regions * MetaspaceShared::core_region_alignment(); |
316 | |
317 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>("_estimated_hashtable_bytes = " SIZE_FORMAT"%" "l" "u" " + " SIZE_FORMAT"%" "l" "u" " = " SIZE_FORMAT"%" "l" "u", |
318 | symbol_table_est, dictionary_est, _estimated_hashtable_bytes); |
319 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>("_estimated_metaspaceobj_bytes = " SIZE_FORMAT"%" "l" "u", _estimated_metaspaceobj_bytes); |
320 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>("total estimate bytes = " SIZE_FORMAT"%" "l" "u", total); |
321 | |
322 | return align_up(total, MetaspaceShared::core_region_alignment()); |
323 | } |
324 | |
325 | address ArchiveBuilder::reserve_buffer() { |
326 | size_t buffer_size = estimate_archive_size(); |
327 | ReservedSpace rs(buffer_size, MetaspaceShared::core_region_alignment(), os::vm_page_size()); |
328 | if (!rs.is_reserved()) { |
329 | log_error(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Error))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Error>("Failed to reserve " SIZE_FORMAT"%" "l" "u" " bytes of output buffer.", buffer_size); |
330 | vm_direct_exit(0); |
331 | } |
332 | |
333 | // buffer_bottom is the lowest address of the 2 core regions (rw, ro) when |
334 | // we are copying the class metadata into the buffer. |
335 | address buffer_bottom = (address)rs.base(); |
336 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>("Reserved output buffer space at " PTR_FORMAT"0x%016" "l" "x" " [" SIZE_FORMAT"%" "l" "u" " bytes]", |
337 | p2i(buffer_bottom), buffer_size); |
338 | _shared_rs = rs; |
339 | |
340 | _buffer_bottom = buffer_bottom; |
341 | _last_verified_top = buffer_bottom; |
342 | _current_dump_space = &_rw_region; |
343 | _num_dump_regions_used = 1; |
344 | _other_region_used_bytes = 0; |
345 | _current_dump_space->init(&_shared_rs, &_shared_vs); |
346 | |
347 | ArchivePtrMarker::initialize(&_ptrmap, &_shared_vs); |
348 | |
349 | // The bottom of the static archive should be mapped at this address by default. |
350 | _requested_static_archive_bottom = (address)MetaspaceShared::requested_base_address(); |
351 | |
352 | // The bottom of the archive (that I am writing now) should be mapped at this address by default. |
353 | address my_archive_requested_bottom; |
354 | |
355 | if (DumpSharedSpaces) { |
356 | my_archive_requested_bottom = _requested_static_archive_bottom; |
357 | } else { |
358 | _mapped_static_archive_bottom = (address)MetaspaceObj::shared_metaspace_base(); |
359 | _mapped_static_archive_top = (address)MetaspaceObj::shared_metaspace_top(); |
360 | assert(_mapped_static_archive_top >= _mapped_static_archive_bottom, "must be")do { if (!(_mapped_static_archive_top >= _mapped_static_archive_bottom )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 360, "assert(" "_mapped_static_archive_top >= _mapped_static_archive_bottom" ") failed", "must be"); ::breakpoint(); } } while (0); |
361 | size_t static_archive_size = _mapped_static_archive_top - _mapped_static_archive_bottom; |
362 | |
363 | // At run time, we will mmap the dynamic archive at my_archive_requested_bottom |
364 | _requested_static_archive_top = _requested_static_archive_bottom + static_archive_size; |
365 | my_archive_requested_bottom = align_up(_requested_static_archive_top, MetaspaceShared::core_region_alignment()); |
366 | |
367 | _requested_dynamic_archive_bottom = my_archive_requested_bottom; |
368 | } |
369 | |
370 | _buffer_to_requested_delta = my_archive_requested_bottom - _buffer_bottom; |
371 | |
372 | address my_archive_requested_top = my_archive_requested_bottom + buffer_size; |
373 | if (my_archive_requested_bottom < _requested_static_archive_bottom || |
374 | my_archive_requested_top <= _requested_static_archive_bottom) { |
375 | // Size overflow. |
376 | log_error(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Error))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Error>("my_archive_requested_bottom = " INTPTR_FORMAT"0x%016" "l" "x", p2i(my_archive_requested_bottom)); |
377 | log_error(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Error))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Error>("my_archive_requested_top = " INTPTR_FORMAT"0x%016" "l" "x", p2i(my_archive_requested_top)); |
378 | log_error(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Error))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Error>("SharedBaseAddress (" INTPTR_FORMAT"0x%016" "l" "x" ") is too high. " |
379 | "Please rerun java -Xshare:dump with a lower value", p2i(_requested_static_archive_bottom)); |
380 | vm_direct_exit(0); |
381 | } |
382 | |
383 | if (DumpSharedSpaces) { |
384 | // We don't want any valid object to be at the very bottom of the archive. |
385 | // See ArchivePtrMarker::mark_pointer(). |
386 | rw_region()->allocate(16); |
387 | } |
388 | |
389 | return buffer_bottom; |
390 | } |
391 | |
392 | void ArchiveBuilder::iterate_sorted_roots(MetaspaceClosure* it, bool is_relocating_pointers) { |
393 | int i; |
394 | |
395 | if (!is_relocating_pointers) { |
396 | // Don't relocate _symbol, so we can safely call decrement_refcount on the |
397 | // original symbols. |
398 | int num_symbols = _symbols->length(); |
399 | for (i = 0; i < num_symbols; i++) { |
400 | it->push(_symbols->adr_at(i)); |
401 | } |
402 | } |
403 | |
404 | int num_klasses = _klasses->length(); |
405 | for (i = 0; i < num_klasses; i++) { |
406 | it->push(_klasses->adr_at(i)); |
407 | } |
408 | |
409 | iterate_roots(it, is_relocating_pointers); |
410 | } |
411 | |
412 | class GatherSortedSourceObjs : public MetaspaceClosure { |
413 | ArchiveBuilder* _builder; |
414 | |
415 | public: |
416 | GatherSortedSourceObjs(ArchiveBuilder* builder) : _builder(builder) {} |
417 | |
418 | virtual bool do_ref(Ref* ref, bool read_only) { |
419 | return _builder->gather_one_source_obj(enclosing_ref(), ref, read_only); |
420 | } |
421 | |
422 | virtual void push_special(SpecialRef type, Ref* ref, intptr_t* p) { |
423 | assert(type == _method_entry_ref, "only special type allowed for now")do { if (!(type == _method_entry_ref)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 423, "assert(" "type == _method_entry_ref" ") failed", "only special type allowed for now" ); ::breakpoint(); } } while (0); |
424 | address src_obj = ref->obj(); |
425 | size_t field_offset = pointer_delta(p, src_obj, sizeof(u1)); |
426 | _builder->add_special_ref(type, src_obj, field_offset); |
427 | }; |
428 | |
429 | virtual void do_pending_ref(Ref* ref) { |
430 | if (ref->obj() != NULL__null) { |
431 | _builder->remember_embedded_pointer_in_copied_obj(enclosing_ref(), ref); |
432 | } |
433 | } |
434 | }; |
435 | |
436 | bool ArchiveBuilder::gather_one_source_obj(MetaspaceClosure::Ref* enclosing_ref, |
437 | MetaspaceClosure::Ref* ref, bool read_only) { |
438 | address src_obj = ref->obj(); |
439 | if (src_obj == NULL__null) { |
440 | return false; |
441 | } |
442 | ref->set_keep_after_pushing(); |
443 | remember_embedded_pointer_in_copied_obj(enclosing_ref, ref); |
444 | |
445 | FollowMode follow_mode = get_follow_mode(ref); |
446 | SourceObjInfo src_info(ref, read_only, follow_mode); |
447 | bool created; |
448 | SourceObjInfo* p = _src_obj_table.put_if_absent(src_obj, src_info, &created); |
449 | if (created) { |
450 | if (_src_obj_table.maybe_grow()) { |
451 | log_info(cds, hashtables)(!(LogImpl<(LogTag::_cds), (LogTag::_hashtables), (LogTag:: __NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG )>::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::_hashtables), (LogTag::__NO_TAG), (LogTag:: __NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write< LogLevel::Info>("Expanded _src_obj_table table to %d", _src_obj_table.table_size()); |
452 | } |
453 | } |
454 | |
455 | assert(p->read_only() == src_info.read_only(), "must be")do { if (!(p->read_only() == src_info.read_only())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 455, "assert(" "p->read_only() == src_info.read_only()" ") failed" , "must be"); ::breakpoint(); } } while (0); |
456 | |
457 | if (created && src_info.should_copy()) { |
458 | ref->set_user_data((void*)p); |
459 | if (read_only) { |
460 | _ro_src_objs.append(enclosing_ref, p); |
461 | } else { |
462 | _rw_src_objs.append(enclosing_ref, p); |
463 | } |
464 | return true; // Need to recurse into this ref only if we are copying it |
465 | } else { |
466 | return false; |
467 | } |
468 | } |
469 | |
470 | void ArchiveBuilder::add_special_ref(MetaspaceClosure::SpecialRef type, address src_obj, size_t field_offset) { |
471 | _special_refs->append(SpecialRefInfo(type, src_obj, field_offset)); |
472 | } |
473 | |
474 | void ArchiveBuilder::remember_embedded_pointer_in_copied_obj(MetaspaceClosure::Ref* enclosing_ref, |
475 | MetaspaceClosure::Ref* ref) { |
476 | assert(ref->obj() != NULL, "should have checked")do { if (!(ref->obj() != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 476, "assert(" "ref->obj() != __null" ") failed", "should have checked" ); ::breakpoint(); } } while (0); |
477 | |
478 | if (enclosing_ref != NULL__null) { |
479 | SourceObjInfo* src_info = (SourceObjInfo*)enclosing_ref->user_data(); |
480 | if (src_info == NULL__null) { |
481 | // source objects of point_to_it/set_to_null types are not copied |
482 | // so we don't need to remember their pointers. |
483 | } else { |
484 | if (src_info->read_only()) { |
485 | _ro_src_objs.remember_embedded_pointer(src_info, ref); |
486 | } else { |
487 | _rw_src_objs.remember_embedded_pointer(src_info, ref); |
488 | } |
489 | } |
490 | } |
491 | } |
492 | |
493 | void ArchiveBuilder::gather_source_objs() { |
494 | ResourceMark rm; |
495 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>("Gathering all archivable objects ... "); |
496 | gather_klasses_and_symbols(); |
497 | GatherSortedSourceObjs doit(this); |
498 | iterate_sorted_roots(&doit, /*is_relocating_pointers=*/false); |
499 | doit.finish(); |
500 | } |
501 | |
502 | bool ArchiveBuilder::is_excluded(Klass* klass) { |
503 | if (klass->is_instance_klass()) { |
504 | InstanceKlass* ik = InstanceKlass::cast(klass); |
505 | return SystemDictionaryShared::is_excluded_class(ik); |
506 | } else if (klass->is_objArray_klass()) { |
507 | if (DynamicDumpSharedSpaces) { |
508 | // Don't support archiving of array klasses for now (WHY???) |
509 | return true; |
510 | } |
511 | Klass* bottom = ObjArrayKlass::cast(klass)->bottom_klass(); |
512 | if (bottom->is_instance_klass()) { |
513 | return SystemDictionaryShared::is_excluded_class(InstanceKlass::cast(bottom)); |
514 | } |
515 | } |
516 | |
517 | return false; |
518 | } |
519 | |
520 | ArchiveBuilder::FollowMode ArchiveBuilder::get_follow_mode(MetaspaceClosure::Ref *ref) { |
521 | address obj = ref->obj(); |
522 | if (MetaspaceShared::is_in_shared_metaspace(obj)) { |
523 | // Don't dump existing shared metadata again. |
524 | return point_to_it; |
525 | } else if (ref->msotype() == MetaspaceObj::MethodDataType) { |
526 | return set_to_null; |
527 | } else { |
528 | if (ref->msotype() == MetaspaceObj::ClassType) { |
529 | Klass* klass = (Klass*)ref->obj(); |
530 | assert(klass->is_klass(), "must be")do { if (!(klass->is_klass())) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 530, "assert(" "klass->is_klass()" ") failed", "must be" ); ::breakpoint(); } } while (0); |
531 | if (is_excluded(klass)) { |
532 | ResourceMark rm; |
533 | log_debug(cds, dynamic)(!(LogImpl<(LogTag::_cds), (LogTag::_dynamic), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::_dynamic), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>("Skipping class (excluded): %s", klass->external_name()); |
534 | return set_to_null; |
535 | } |
536 | } |
537 | |
538 | return make_a_copy; |
539 | } |
540 | } |
541 | |
542 | void ArchiveBuilder::start_dump_space(DumpRegion* next) { |
543 | address bottom = _last_verified_top; |
544 | address top = (address)(current_dump_space()->top()); |
545 | _other_region_used_bytes += size_t(top - bottom); |
546 | |
547 | current_dump_space()->pack(next); |
548 | _current_dump_space = next; |
549 | _num_dump_regions_used ++; |
550 | |
551 | _last_verified_top = (address)(current_dump_space()->top()); |
552 | } |
553 | |
554 | void ArchiveBuilder::verify_estimate_size(size_t estimate, const char* which) { |
555 | address bottom = _last_verified_top; |
556 | address top = (address)(current_dump_space()->top()); |
557 | size_t used = size_t(top - bottom) + _other_region_used_bytes; |
558 | int diff = int(estimate) - int(used); |
559 | |
560 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>("%s estimate = " SIZE_FORMAT"%" "l" "u" " used = " SIZE_FORMAT"%" "l" "u" "; diff = %d bytes", which, estimate, used, diff); |
561 | assert(diff >= 0, "Estimate is too small")do { if (!(diff >= 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 561, "assert(" "diff >= 0" ") failed", "Estimate is too small" ); ::breakpoint(); } } while (0); |
562 | |
563 | _last_verified_top = top; |
564 | _other_region_used_bytes = 0; |
565 | } |
566 | |
567 | void ArchiveBuilder::dump_rw_metadata() { |
568 | ResourceMark rm; |
569 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>("Allocating RW objects ... "); |
570 | make_shallow_copies(&_rw_region, &_rw_src_objs); |
571 | |
572 | #if INCLUDE_CDS_JAVA_HEAP1 |
573 | if (is_dumping_full_module_graph()) { |
574 | // Archive the ModuleEntry's and PackageEntry's of the 3 built-in loaders |
575 | char* start = rw_region()->top(); |
576 | ClassLoaderDataShared::allocate_archived_tables(); |
577 | alloc_stats()->record_modules(rw_region()->top() - start, /*read_only*/false); |
578 | } |
579 | #endif |
580 | } |
581 | |
582 | void ArchiveBuilder::dump_ro_metadata() { |
583 | ResourceMark rm; |
584 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>("Allocating RO objects ... "); |
585 | |
586 | start_dump_space(&_ro_region); |
587 | make_shallow_copies(&_ro_region, &_ro_src_objs); |
588 | |
589 | #if INCLUDE_CDS_JAVA_HEAP1 |
590 | if (is_dumping_full_module_graph()) { |
591 | char* start = ro_region()->top(); |
592 | ClassLoaderDataShared::init_archived_tables(); |
593 | alloc_stats()->record_modules(ro_region()->top() - start, /*read_only*/true); |
594 | } |
595 | #endif |
596 | } |
597 | |
598 | void ArchiveBuilder::make_shallow_copies(DumpRegion *dump_region, |
599 | const ArchiveBuilder::SourceObjList* src_objs) { |
600 | for (int i = 0; i < src_objs->objs()->length(); i++) { |
601 | make_shallow_copy(dump_region, src_objs->objs()->at(i)); |
602 | } |
603 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>("done (%d objects)", src_objs->objs()->length()); |
604 | } |
605 | |
606 | void ArchiveBuilder::make_shallow_copy(DumpRegion *dump_region, SourceObjInfo* src_info) { |
607 | MetaspaceClosure::Ref* ref = src_info->ref(); |
608 | address src = ref->obj(); |
609 | int bytes = src_info->size_in_bytes(); |
610 | char* dest; |
611 | char* oldtop; |
612 | char* newtop; |
613 | |
614 | oldtop = dump_region->top(); |
615 | if (ref->msotype() == MetaspaceObj::ClassType) { |
616 | // Save a pointer immediate in front of an InstanceKlass, so |
617 | // we can do a quick lookup from InstanceKlass* -> RunTimeClassInfo* |
618 | // without building another hashtable. See RunTimeClassInfo::get_for() |
619 | // in systemDictionaryShared.cpp. |
620 | Klass* klass = (Klass*)src; |
621 | if (klass->is_instance_klass()) { |
622 | SystemDictionaryShared::validate_before_archiving(InstanceKlass::cast(klass)); |
623 | dump_region->allocate(sizeof(address)); |
624 | } |
625 | } |
626 | dest = dump_region->allocate(bytes); |
627 | newtop = dump_region->top(); |
628 | |
629 | memcpy(dest, src, bytes); |
630 | |
631 | intptr_t* archived_vtable = CppVtables::get_archived_vtable(ref->msotype(), (address)dest); |
632 | if (archived_vtable != NULL__null) { |
633 | *(address*)dest = (address)archived_vtable; |
634 | ArchivePtrMarker::mark_pointer((address*)dest); |
635 | } |
636 | |
637 | log_trace(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Trace))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Trace>("Copy: " PTR_FORMAT"0x%016" "l" "x" " ==> " PTR_FORMAT"0x%016" "l" "x" " %d", p2i(src), p2i(dest), bytes); |
638 | src_info->set_dumped_addr((address)dest); |
639 | |
640 | _alloc_stats.record(ref->msotype(), int(newtop - oldtop), src_info->read_only()); |
641 | } |
642 | |
643 | address ArchiveBuilder::get_dumped_addr(address src_obj) const { |
644 | SourceObjInfo* p = _src_obj_table.get(src_obj); |
645 | assert(p != NULL, "must be")do { if (!(p != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 645, "assert(" "p != __null" ") failed", "must be"); ::breakpoint (); } } while (0); |
646 | |
647 | return p->dumped_addr(); |
648 | } |
649 | |
650 | void ArchiveBuilder::relocate_embedded_pointers(ArchiveBuilder::SourceObjList* src_objs) { |
651 | for (int i = 0; i < src_objs->objs()->length(); i++) { |
652 | src_objs->relocate(i, this); |
653 | } |
654 | } |
655 | |
656 | void ArchiveBuilder::update_special_refs() { |
657 | for (int i = 0; i < _special_refs->length(); i++) { |
658 | SpecialRefInfo s = _special_refs->at(i); |
659 | size_t field_offset = s.field_offset(); |
660 | address src_obj = s.src_obj(); |
661 | address dst_obj = get_dumped_addr(src_obj); |
662 | intptr_t* src_p = (intptr_t*)(src_obj + field_offset); |
663 | intptr_t* dst_p = (intptr_t*)(dst_obj + field_offset); |
664 | assert(s.type() == MetaspaceClosure::_method_entry_ref, "only special type allowed for now")do { if (!(s.type() == MetaspaceClosure::_method_entry_ref)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 664, "assert(" "s.type() == MetaspaceClosure::_method_entry_ref" ") failed", "only special type allowed for now"); ::breakpoint (); } } while (0); |
665 | |
666 | assert(*src_p == *dst_p, "must be a copy")do { if (!(*src_p == *dst_p)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 666, "assert(" "*src_p == *dst_p" ") failed", "must be a copy" ); ::breakpoint(); } } while (0); |
667 | ArchivePtrMarker::mark_pointer((address*)dst_p); |
668 | } |
669 | } |
670 | |
671 | class RefRelocator: public MetaspaceClosure { |
672 | ArchiveBuilder* _builder; |
673 | |
674 | public: |
675 | RefRelocator(ArchiveBuilder* builder) : _builder(builder) {} |
676 | |
677 | virtual bool do_ref(Ref* ref, bool read_only) { |
678 | if (ref->not_null()) { |
679 | ref->update(_builder->get_dumped_addr(ref->obj())); |
680 | ArchivePtrMarker::mark_pointer(ref->addr()); |
681 | } |
682 | return false; // Do not recurse. |
683 | } |
684 | }; |
685 | |
686 | void ArchiveBuilder::relocate_roots() { |
687 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>("Relocating external roots ... "); |
688 | ResourceMark rm; |
689 | RefRelocator doit(this); |
690 | iterate_sorted_roots(&doit, /*is_relocating_pointers=*/true); |
691 | doit.finish(); |
692 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>("done"); |
693 | } |
694 | |
695 | void ArchiveBuilder::relocate_metaspaceobj_embedded_pointers() { |
696 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>("Relocating embedded pointers in core regions ... "); |
697 | relocate_embedded_pointers(&_rw_src_objs); |
698 | relocate_embedded_pointers(&_ro_src_objs); |
699 | update_special_refs(); |
700 | } |
701 | |
702 | // We must relocate vmClasses::_klasses[] only after we have copied the |
703 | // java objects in during dump_java_heap_objects(): during the object copy, we operate on |
704 | // old objects which assert that their klass is the original klass. |
705 | void ArchiveBuilder::relocate_vm_classes() { |
706 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>("Relocating vmClasses::_klasses[] ... "); |
707 | ResourceMark rm; |
708 | RefRelocator doit(this); |
709 | vmClasses::metaspace_pointers_do(&doit); |
710 | } |
711 | |
712 | void ArchiveBuilder::make_klasses_shareable() { |
713 | int num_instance_klasses = 0; |
714 | int num_boot_klasses = 0; |
715 | int num_platform_klasses = 0; |
716 | int num_app_klasses = 0; |
717 | int num_hidden_klasses = 0; |
718 | int num_unlinked_klasses = 0; |
719 | int num_unregistered_klasses = 0; |
720 | int num_obj_array_klasses = 0; |
721 | int num_type_array_klasses = 0; |
722 | |
723 | for (int i = 0; i < klasses()->length(); i++) { |
724 | const char* type; |
725 | const char* unlinked = ""; |
726 | const char* hidden = ""; |
727 | Klass* k = klasses()->at(i); |
728 | k->remove_java_mirror(); |
729 | if (k->is_objArray_klass()) { |
730 | // InstanceKlass and TypeArrayKlass will in turn call remove_unshareable_info |
731 | // on their array classes. |
732 | num_obj_array_klasses ++; |
733 | type = "array"; |
734 | } else if (k->is_typeArray_klass()) { |
735 | num_type_array_klasses ++; |
736 | type = "array"; |
737 | k->remove_unshareable_info(); |
738 | } else { |
739 | assert(k->is_instance_klass(), " must be")do { if (!(k->is_instance_klass())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 739, "assert(" "k->is_instance_klass()" ") failed", " must be" ); ::breakpoint(); } } while (0); |
740 | num_instance_klasses ++; |
741 | InstanceKlass* ik = InstanceKlass::cast(k); |
742 | if (DynamicDumpSharedSpaces) { |
743 | // For static dump, class loader type are already set. |
744 | ik->assign_class_loader_type(); |
745 | } |
746 | if (ik->is_shared_boot_class()) { |
747 | type = "boot"; |
748 | num_boot_klasses ++; |
749 | } else if (ik->is_shared_platform_class()) { |
750 | type = "plat"; |
751 | num_platform_klasses ++; |
752 | } else if (ik->is_shared_app_class()) { |
753 | type = "app"; |
754 | num_app_klasses ++; |
755 | } else { |
756 | assert(ik->is_shared_unregistered_class(), "must be")do { if (!(ik->is_shared_unregistered_class())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 756, "assert(" "ik->is_shared_unregistered_class()" ") failed" , "must be"); ::breakpoint(); } } while (0); |
757 | type = "unreg"; |
758 | num_unregistered_klasses ++; |
759 | } |
760 | |
761 | if (!ik->is_linked()) { |
762 | num_unlinked_klasses ++; |
763 | unlinked = " ** unlinked"; |
764 | } |
765 | |
766 | if (ik->is_hidden()) { |
767 | num_hidden_klasses ++; |
768 | hidden = " ** hidden"; |
769 | } |
770 | |
771 | MetaspaceShared::rewrite_nofast_bytecodes_and_calculate_fingerprints(Thread::current(), ik); |
772 | ik->remove_unshareable_info(); |
773 | } |
774 | |
775 | if (log_is_enabled(Debug, cds, class)(LogImpl<(LogTag::_cds), (LogTag::_class), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) { |
776 | ResourceMark rm; |
777 | log_debug(cds, class)(!(LogImpl<(LogTag::_cds), (LogTag::_class), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::_class), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>("klasses[%5d] = " PTR_FORMAT"0x%016" "l" "x" " %-5s %s%s%s", i, p2i(to_requested(k)), type, k->external_name(), hidden, unlinked); |
778 | } |
779 | } |
780 | |
781 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>("Number of classes %d", num_instance_klasses + num_obj_array_klasses + num_type_array_klasses); |
782 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>(" instance classes = %5d", num_instance_klasses); |
783 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>(" boot = %5d", num_boot_klasses); |
784 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>(" app = %5d", num_app_klasses); |
785 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>(" platform = %5d", num_platform_klasses); |
786 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>(" unregistered = %5d", num_unregistered_klasses); |
787 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>(" (hidden) = %5d", num_hidden_klasses); |
788 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>(" (unlinked) = %5d", num_unlinked_klasses); |
789 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>(" obj array classes = %5d", num_obj_array_klasses); |
790 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>(" type array classes = %5d", num_type_array_klasses); |
791 | log_info(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>(" symbols = %5d", _symbols->length()); |
792 | } |
793 | |
794 | uintx ArchiveBuilder::buffer_to_offset(address p) const { |
795 | address requested_p = to_requested(p); |
796 | assert(requested_p >= _requested_static_archive_bottom, "must be")do { if (!(requested_p >= _requested_static_archive_bottom )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 796, "assert(" "requested_p >= _requested_static_archive_bottom" ") failed", "must be"); ::breakpoint(); } } while (0); |
797 | return requested_p - _requested_static_archive_bottom; |
798 | } |
799 | |
800 | uintx ArchiveBuilder::any_to_offset(address p) const { |
801 | if (is_in_mapped_static_archive(p)) { |
802 | assert(DynamicDumpSharedSpaces, "must be")do { if (!(DynamicDumpSharedSpaces)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 802, "assert(" "DynamicDumpSharedSpaces" ") failed", "must be" ); ::breakpoint(); } } while (0); |
803 | return p - _mapped_static_archive_bottom; |
804 | } |
805 | return buffer_to_offset(p); |
806 | } |
807 | |
808 | // Update a Java object to point its Klass* to the new location after |
809 | // shared archive has been compacted. |
810 | void ArchiveBuilder::relocate_klass_ptr(oop o) { |
811 | assert(DumpSharedSpaces, "sanity")do { if (!(DumpSharedSpaces)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 811, "assert(" "DumpSharedSpaces" ") failed", "sanity"); :: breakpoint(); } } while (0); |
812 | Klass* k = get_relocated_klass(o->klass()); |
813 | Klass* requested_k = to_requested(k); |
814 | narrowKlass nk = CompressedKlassPointers::encode_not_null(requested_k, _requested_static_archive_bottom); |
815 | o->set_narrow_klass(nk); |
816 | } |
817 | |
818 | // RelocateBufferToRequested --- Relocate all the pointers in rw/ro, |
819 | // so that the archive can be mapped to the "requested" location without runtime relocation. |
820 | // |
821 | // - See ArchiveBuilder header for the definition of "buffer", "mapped" and "requested" |
822 | // - ArchivePtrMarker::ptrmap() marks all the pointers in the rw/ro regions |
823 | // - Every pointer must have one of the following values: |
824 | // [a] NULL: |
825 | // No relocation is needed. Remove this pointer from ptrmap so we don't need to |
826 | // consider it at runtime. |
827 | // [b] Points into an object X which is inside the buffer: |
828 | // Adjust this pointer by _buffer_to_requested_delta, so it points to X |
829 | // when the archive is mapped at the requested location. |
830 | // [c] Points into an object Y which is inside mapped static archive: |
831 | // - This happens only during dynamic dump |
832 | // - Adjust this pointer by _mapped_to_requested_static_archive_delta, |
833 | // so it points to Y when the static archive is mapped at the requested location. |
834 | template <bool STATIC_DUMP> |
835 | class RelocateBufferToRequested : public BitMapClosure { |
836 | ArchiveBuilder* _builder; |
837 | address _buffer_bottom; |
838 | intx _buffer_to_requested_delta; |
839 | intx _mapped_to_requested_static_archive_delta; |
840 | size_t _max_non_null_offset; |
841 | |
842 | public: |
843 | RelocateBufferToRequested(ArchiveBuilder* builder) { |
844 | _builder = builder; |
845 | _buffer_bottom = _builder->buffer_bottom(); |
846 | _buffer_to_requested_delta = builder->buffer_to_requested_delta(); |
847 | _mapped_to_requested_static_archive_delta = builder->requested_static_archive_bottom() - builder->mapped_static_archive_bottom(); |
848 | _max_non_null_offset = 0; |
849 | |
850 | address bottom = _builder->buffer_bottom(); |
851 | address top = _builder->buffer_top(); |
852 | address new_bottom = bottom + _buffer_to_requested_delta; |
853 | address new_top = top + _buffer_to_requested_delta; |
854 | log_debug(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>("Relocating archive from [" INTPTR_FORMAT"0x%016" "l" "x" " - " INTPTR_FORMAT"0x%016" "l" "x" "] to " |
855 | "[" INTPTR_FORMAT"0x%016" "l" "x" " - " INTPTR_FORMAT"0x%016" "l" "x" "]", |
856 | p2i(bottom), p2i(top), |
857 | p2i(new_bottom), p2i(new_top)); |
858 | } |
859 | |
860 | bool do_bit(size_t offset) { |
861 | address* p = (address*)_buffer_bottom + offset; |
862 | assert(_builder->is_in_buffer_space(p), "pointer must live in buffer space")do { if (!(_builder->is_in_buffer_space(p))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 862, "assert(" "_builder->is_in_buffer_space(p)" ") failed" , "pointer must live in buffer space"); ::breakpoint(); } } while (0); |
863 | |
864 | if (*p == NULL__null) { |
865 | // todo -- clear bit, etc |
866 | ArchivePtrMarker::ptrmap()->clear_bit(offset); |
867 | } else { |
868 | if (STATIC_DUMP) { |
869 | assert(_builder->is_in_buffer_space(*p), "old pointer must point inside buffer space")do { if (!(_builder->is_in_buffer_space(*p))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 869, "assert(" "_builder->is_in_buffer_space(*p)" ") failed" , "old pointer must point inside buffer space"); ::breakpoint (); } } while (0); |
870 | *p += _buffer_to_requested_delta; |
871 | assert(_builder->is_in_requested_static_archive(*p), "new pointer must point inside requested archive")do { if (!(_builder->is_in_requested_static_archive(*p))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 871, "assert(" "_builder->is_in_requested_static_archive(*p)" ") failed", "new pointer must point inside requested archive" ); ::breakpoint(); } } while (0); |
872 | } else { |
873 | if (_builder->is_in_buffer_space(*p)) { |
874 | *p += _buffer_to_requested_delta; |
875 | // assert is in requested dynamic archive |
876 | } else { |
877 | assert(_builder->is_in_mapped_static_archive(*p), "old pointer must point inside buffer space or mapped static archive")do { if (!(_builder->is_in_mapped_static_archive(*p))) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 877, "assert(" "_builder->is_in_mapped_static_archive(*p)" ") failed", "old pointer must point inside buffer space or mapped static archive" ); ::breakpoint(); } } while (0); |
878 | *p += _mapped_to_requested_static_archive_delta; |
879 | assert(_builder->is_in_requested_static_archive(*p), "new pointer must point inside requested archive")do { if (!(_builder->is_in_requested_static_archive(*p))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 879, "assert(" "_builder->is_in_requested_static_archive(*p)" ") failed", "new pointer must point inside requested archive" ); ::breakpoint(); } } while (0); |
880 | } |
881 | } |
882 | _max_non_null_offset = offset; |
883 | } |
884 | |
885 | return true; // keep iterating |
886 | } |
887 | |
888 | void doit() { |
889 | ArchivePtrMarker::ptrmap()->iterate(this); |
890 | ArchivePtrMarker::compact(_max_non_null_offset); |
891 | } |
892 | }; |
893 | |
894 | |
895 | void ArchiveBuilder::relocate_to_requested() { |
896 | ro_region()->pack(); |
897 | |
898 | size_t my_archive_size = buffer_top() - buffer_bottom(); |
899 | |
900 | if (DumpSharedSpaces) { |
901 | _requested_static_archive_top = _requested_static_archive_bottom + my_archive_size; |
902 | RelocateBufferToRequested<true> patcher(this); |
903 | patcher.doit(); |
904 | } else { |
905 | assert(DynamicDumpSharedSpaces, "must be")do { if (!(DynamicDumpSharedSpaces)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 905, "assert(" "DynamicDumpSharedSpaces" ") failed", "must be" ); ::breakpoint(); } } while (0); |
906 | _requested_dynamic_archive_top = _requested_dynamic_archive_bottom + my_archive_size; |
907 | RelocateBufferToRequested<false> patcher(this); |
908 | patcher.doit(); |
909 | } |
910 | } |
911 | |
912 | // Write detailed info to a mapfile to analyze contents of the archive. |
913 | // static dump: |
914 | // java -Xshare:dump -Xlog:cds+map=trace:file=cds.map:none:filesize=0 |
915 | // dynamic dump: |
916 | // java -cp MyApp.jar -XX:ArchiveClassesAtExit=MyApp.jsa \ |
917 | // -Xlog:cds+map=trace:file=cds.map:none:filesize=0 MyApp |
918 | // |
919 | // We need to do some address translation because the buffers used at dump time may be mapped to |
920 | // a different location at runtime. At dump time, the buffers may be at arbitrary locations |
921 | // picked by the OS. At runtime, we try to map at a fixed location (SharedBaseAddress). For |
922 | // consistency, we log everything using runtime addresses. |
923 | class ArchiveBuilder::CDSMapLogger : AllStatic { |
924 | static intx buffer_to_runtime_delta() { |
925 | // Translate the buffers used by the RW/RO regions to their eventual (requested) locations |
926 | // at runtime. |
927 | return ArchiveBuilder::current()->buffer_to_requested_delta(); |
928 | } |
929 | |
930 | // rw/ro regions only |
931 | static void write_dump_region(const char* name, DumpRegion* region) { |
932 | address region_base = address(region->base()); |
933 | address region_top = address(region->top()); |
934 | write_region(name, region_base, region_top, region_base + buffer_to_runtime_delta()); |
935 | } |
936 | |
937 | #define _LOG_PREFIX PTR_FORMAT"0x%016" "l" "x" ": @@ %-17s %d" |
938 | |
939 | static void write_klass(Klass* k, address runtime_dest, const char* type_name, int bytes, Thread* current) { |
940 | ResourceMark rm(current); |
941 | log_debug(cds, map)(!(LogImpl<(LogTag::_cds), (LogTag::_map), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::_map), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>(_LOG_PREFIX " %s", |
942 | p2i(runtime_dest), type_name, bytes, k->external_name()); |
943 | } |
944 | static void write_method(Method* m, address runtime_dest, const char* type_name, int bytes, Thread* current) { |
945 | ResourceMark rm(current); |
946 | log_debug(cds, map)(!(LogImpl<(LogTag::_cds), (LogTag::_map), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::_map), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>(_LOG_PREFIX " %s", |
947 | p2i(runtime_dest), type_name, bytes, m->external_name()); |
948 | } |
949 | |
950 | // rw/ro regions only |
951 | static void write_objects(DumpRegion* region, const ArchiveBuilder::SourceObjList* src_objs) { |
952 | address last_obj_base = address(region->base()); |
953 | address last_obj_end = address(region->base()); |
954 | address region_end = address(region->end()); |
955 | Thread* current = Thread::current(); |
956 | for (int i = 0; i < src_objs->objs()->length(); i++) { |
957 | SourceObjInfo* src_info = src_objs->at(i); |
958 | address src = src_info->orig_obj(); |
959 | address dest = src_info->dumped_addr(); |
960 | write_data(last_obj_base, dest, last_obj_base + buffer_to_runtime_delta()); |
961 | address runtime_dest = dest + buffer_to_runtime_delta(); |
962 | int bytes = src_info->size_in_bytes(); |
963 | |
964 | MetaspaceObj::Type type = src_info->msotype(); |
965 | const char* type_name = MetaspaceObj::type_name(type); |
966 | |
967 | switch (type) { |
968 | case MetaspaceObj::ClassType: |
969 | write_klass((Klass*)src, runtime_dest, type_name, bytes, current); |
970 | break; |
971 | case MetaspaceObj::ConstantPoolType: |
972 | write_klass(((ConstantPool*)src)->pool_holder(), |
973 | runtime_dest, type_name, bytes, current); |
974 | break; |
975 | case MetaspaceObj::ConstantPoolCacheType: |
976 | write_klass(((ConstantPoolCache*)src)->constant_pool()->pool_holder(), |
977 | runtime_dest, type_name, bytes, current); |
978 | break; |
979 | case MetaspaceObj::MethodType: |
980 | write_method((Method*)src, runtime_dest, type_name, bytes, current); |
981 | break; |
982 | case MetaspaceObj::ConstMethodType: |
983 | write_method(((ConstMethod*)src)->method(), runtime_dest, type_name, bytes, current); |
984 | break; |
985 | case MetaspaceObj::SymbolType: |
986 | { |
987 | ResourceMark rm(current); |
988 | Symbol* s = (Symbol*)src; |
989 | log_debug(cds, map)(!(LogImpl<(LogTag::_cds), (LogTag::_map), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::_map), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>(_LOG_PREFIX " %s", p2i(runtime_dest), type_name, bytes, |
990 | s->as_quoted_ascii()); |
991 | } |
992 | break; |
993 | default: |
994 | log_debug(cds, map)(!(LogImpl<(LogTag::_cds), (LogTag::_map), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::_map), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>(_LOG_PREFIX, p2i(runtime_dest), type_name, bytes); |
995 | break; |
996 | } |
997 | |
998 | last_obj_base = dest; |
999 | last_obj_end = dest + bytes; |
1000 | } |
1001 | |
1002 | write_data(last_obj_base, last_obj_end, last_obj_base + buffer_to_runtime_delta()); |
1003 | if (last_obj_end < region_end) { |
1004 | log_debug(cds, map)(!(LogImpl<(LogTag::_cds), (LogTag::_map), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::_map), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>(PTR_FORMAT"0x%016" "l" "x" ": @@ Misc data " SIZE_FORMAT"%" "l" "u" " bytes", |
1005 | p2i(last_obj_end + buffer_to_runtime_delta()), |
1006 | size_t(region_end - last_obj_end)); |
1007 | write_data(last_obj_end, region_end, last_obj_end + buffer_to_runtime_delta()); |
1008 | } |
1009 | } |
1010 | |
1011 | #undef _LOG_PREFIX |
1012 | |
1013 | // Write information about a region, whose address at dump time is [base .. top). At |
1014 | // runtime, this region will be mapped to runtime_base. runtime_base is 0 if this |
1015 | // region will be mapped at os-selected addresses (such as the bitmap region), or will |
1016 | // be accessed with os::read (the header). |
1017 | static void write_region(const char* name, address base, address top, address runtime_base) { |
1018 | size_t size = top - base; |
1019 | base = runtime_base; |
1020 | top = runtime_base + size; |
1021 | log_info(cds, map)(!(LogImpl<(LogTag::_cds), (LogTag::_map), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::_map), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>("[%-18s " PTR_FORMAT"0x%016" "l" "x" " - " PTR_FORMAT"0x%016" "l" "x" " " SIZE_FORMAT_W(9)"%" "9" "l" "u" " bytes]", |
1022 | name, p2i(base), p2i(top), size); |
1023 | } |
1024 | |
1025 | // open and closed archive regions |
1026 | static void write_heap_region(const char* which, GrowableArray<MemRegion> *regions) { |
1027 | for (int i = 0; i < regions->length(); i++) { |
1028 | address start = address(regions->at(i).start()); |
1029 | address end = address(regions->at(i).end()); |
1030 | write_region(which, start, end, start); |
1031 | write_data(start, end, start); |
1032 | } |
1033 | } |
1034 | |
1035 | // Dump all the data [base...top). Pretend that the base address |
1036 | // will be mapped to runtime_base at run-time. |
1037 | static void write_data(address base, address top, address runtime_base) { |
1038 | assert(top >= base, "must be")do { if (!(top >= base)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 1038, "assert(" "top >= base" ") failed", "must be"); :: breakpoint(); } } while (0); |
1039 | |
1040 | LogStreamHandle(Trace, cds, map)LogStreamTemplate<LogLevel::Trace, (LogTag::_cds), (LogTag ::_map), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG)> lsh; |
1041 | if (lsh.is_enabled()) { |
1042 | os::print_hex_dump(&lsh, base, top, sizeof(address), 32, runtime_base); |
1043 | } |
1044 | } |
1045 | |
1046 | static void write_header(FileMapInfo* mapinfo) { |
1047 | LogStreamHandle(Info, cds, map)LogStreamTemplate<LogLevel::Info, (LogTag::_cds), (LogTag:: _map), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG)> lsh; |
1048 | if (lsh.is_enabled()) { |
1049 | mapinfo->print(&lsh); |
1050 | } |
1051 | } |
1052 | |
1053 | public: |
1054 | static void write(ArchiveBuilder* builder, FileMapInfo* mapinfo, |
1055 | GrowableArray<MemRegion> *closed_heap_regions, |
1056 | GrowableArray<MemRegion> *open_heap_regions, |
1057 | char* bitmap, size_t bitmap_size_in_bytes) { |
1058 | log_info(cds, map)(!(LogImpl<(LogTag::_cds), (LogTag::_map), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::_map), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>("%s CDS archive map for %s", DumpSharedSpaces ? "Static" : "Dynamic", mapinfo->full_path()); |
1059 | |
1060 | address header = address(mapinfo->header()); |
1061 | address header_end = header + mapinfo->header()->header_size(); |
1062 | write_region("header", header, header_end, 0); |
1063 | write_header(mapinfo); |
1064 | write_data(header, header_end, 0); |
1065 | |
1066 | DumpRegion* rw_region = &builder->_rw_region; |
1067 | DumpRegion* ro_region = &builder->_ro_region; |
1068 | |
1069 | write_dump_region("rw region", rw_region); |
1070 | write_objects(rw_region, &builder->_rw_src_objs); |
1071 | |
1072 | write_dump_region("ro region", ro_region); |
1073 | write_objects(ro_region, &builder->_ro_src_objs); |
1074 | |
1075 | address bitmap_end = address(bitmap + bitmap_size_in_bytes); |
1076 | write_region("bitmap", address(bitmap), bitmap_end, 0); |
1077 | write_data(header, header_end, 0); |
1078 | |
1079 | if (closed_heap_regions != NULL__null) { |
1080 | write_heap_region("closed heap region", closed_heap_regions); |
1081 | } |
1082 | if (open_heap_regions != NULL__null) { |
1083 | write_heap_region("open heap region", open_heap_regions); |
1084 | } |
1085 | |
1086 | log_info(cds, map)(!(LogImpl<(LogTag::_cds), (LogTag::_map), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::_map), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>("[End of CDS archive map]"); |
1087 | } |
1088 | }; |
1089 | |
1090 | void ArchiveBuilder::print_stats() { |
1091 | _alloc_stats.print_stats(int(_ro_region.used()), int(_rw_region.used())); |
1092 | } |
1093 | |
1094 | void ArchiveBuilder::clean_up_src_obj_table() { |
1095 | SrcObjTableCleaner cleaner; |
1096 | _src_obj_table.iterate(&cleaner); |
1097 | } |
1098 | |
1099 | void ArchiveBuilder::write_archive(FileMapInfo* mapinfo, |
1100 | GrowableArray<MemRegion>* closed_heap_regions, |
1101 | GrowableArray<MemRegion>* open_heap_regions, |
1102 | GrowableArray<ArchiveHeapOopmapInfo>* closed_heap_oopmaps, |
1103 | GrowableArray<ArchiveHeapOopmapInfo>* open_heap_oopmaps) { |
1104 | // Make sure NUM_CDS_REGIONS (exported in cds.h) agrees with |
1105 | // MetaspaceShared::n_regions (internal to hotspot). |
1106 | assert(NUM_CDS_REGIONS == MetaspaceShared::n_regions, "sanity")do { if (!(7 == MetaspaceShared::n_regions)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 1106, "assert(" "7 == MetaspaceShared::n_regions" ") failed" , "sanity"); ::breakpoint(); } } while (0); |
1107 | |
1108 | write_region(mapinfo, MetaspaceShared::rw, &_rw_region, /*read_only=*/false,/*allow_exec=*/false); |
1109 | write_region(mapinfo, MetaspaceShared::ro, &_ro_region, /*read_only=*/true, /*allow_exec=*/false); |
1110 | |
1111 | size_t bitmap_size_in_bytes; |
1112 | char* bitmap = mapinfo->write_bitmap_region(ArchivePtrMarker::ptrmap(), closed_heap_oopmaps, open_heap_oopmaps, |
1113 | bitmap_size_in_bytes); |
1114 | |
1115 | if (closed_heap_regions != NULL__null) { |
1116 | _total_closed_heap_region_size = mapinfo->write_heap_regions( |
1117 | closed_heap_regions, |
1118 | closed_heap_oopmaps, |
1119 | MetaspaceShared::first_closed_heap_region, |
1120 | MetaspaceShared::max_num_closed_heap_regions); |
1121 | _total_open_heap_region_size = mapinfo->write_heap_regions( |
1122 | open_heap_regions, |
1123 | open_heap_oopmaps, |
1124 | MetaspaceShared::first_open_heap_region, |
1125 | MetaspaceShared::max_num_open_heap_regions); |
1126 | } |
1127 | |
1128 | print_region_stats(mapinfo, closed_heap_regions, open_heap_regions); |
1129 | |
1130 | mapinfo->set_requested_base((char*)MetaspaceShared::requested_base_address()); |
1131 | mapinfo->set_header_crc(mapinfo->compute_header_crc()); |
1132 | // After this point, we should not write any data into mapinfo->header() since this |
1133 | // would corrupt its checksum we have calculated before. |
1134 | mapinfo->write_header(); |
1135 | mapinfo->close(); |
1136 | |
1137 | if (log_is_enabled(Info, cds)(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) { |
1138 | print_stats(); |
1139 | } |
1140 | |
1141 | if (log_is_enabled(Info, cds, map)(LogImpl<(LogTag::_cds), (LogTag::_map), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) { |
1142 | CDSMapLogger::write(this, mapinfo, closed_heap_regions, open_heap_regions, |
1143 | bitmap, bitmap_size_in_bytes); |
1144 | } |
1145 | FREE_C_HEAP_ARRAY(char, bitmap)FreeHeap((char*)(bitmap)); |
1146 | } |
1147 | |
1148 | void ArchiveBuilder::write_region(FileMapInfo* mapinfo, int region_idx, DumpRegion* dump_region, bool read_only, bool allow_exec) { |
1149 | mapinfo->write_region(region_idx, dump_region->base(), dump_region->used(), read_only, allow_exec); |
1150 | } |
1151 | |
1152 | void ArchiveBuilder::print_region_stats(FileMapInfo *mapinfo, |
1153 | GrowableArray<MemRegion>* closed_heap_regions, |
1154 | GrowableArray<MemRegion>* open_heap_regions) { |
1155 | // Print statistics of all the regions |
1156 | const size_t bitmap_used = mapinfo->space_at(MetaspaceShared::bm)->used(); |
1157 | const size_t bitmap_reserved = mapinfo->space_at(MetaspaceShared::bm)->used_aligned(); |
1158 | const size_t total_reserved = _ro_region.reserved() + _rw_region.reserved() + |
1159 | bitmap_reserved + |
1160 | _total_closed_heap_region_size + |
1161 | _total_open_heap_region_size; |
1162 | const size_t total_bytes = _ro_region.used() + _rw_region.used() + |
1163 | bitmap_used + |
1164 | _total_closed_heap_region_size + |
1165 | _total_open_heap_region_size; |
1166 | const double total_u_perc = percent_of(total_bytes, total_reserved); |
1167 | |
1168 | _rw_region.print(total_reserved); |
1169 | _ro_region.print(total_reserved); |
1170 | |
1171 | print_bitmap_region_stats(bitmap_used, total_reserved); |
1172 | |
1173 | if (closed_heap_regions != NULL__null) { |
1174 | print_heap_region_stats(closed_heap_regions, "ca", total_reserved); |
1175 | print_heap_region_stats(open_heap_regions, "oa", total_reserved); |
1176 | } |
1177 | |
1178 | log_debug(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>("total : " SIZE_FORMAT_W(9)"%" "9" "l" "u" " [100.0%% of total] out of " SIZE_FORMAT_W(9)"%" "9" "l" "u" " bytes [%5.1f%% used]", |
1179 | total_bytes, total_reserved, total_u_perc); |
1180 | } |
1181 | |
1182 | void ArchiveBuilder::print_bitmap_region_stats(size_t size, size_t total_size) { |
1183 | log_debug(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>("bm space: " SIZE_FORMAT_W(9)"%" "9" "l" "u" " [ %4.1f%% of total] out of " SIZE_FORMAT_W(9)"%" "9" "l" "u" " bytes [100.0%% used]", |
1184 | size, size/double(total_size)*100.0, size); |
1185 | } |
1186 | |
1187 | void ArchiveBuilder::print_heap_region_stats(GrowableArray<MemRegion>* regions, |
1188 | const char *name, size_t total_size) { |
1189 | int arr_len = regions == NULL__null ? 0 : regions->length(); |
1190 | for (int i = 0; i < arr_len; i++) { |
1191 | char* start = (char*)regions->at(i).start(); |
1192 | size_t size = regions->at(i).byte_size(); |
1193 | char* top = start + size; |
Value stored to 'top' during its initialization is never read | |
1194 | log_debug(cds)(!(LogImpl<(LogTag::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_cds), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>("%s%d space: " SIZE_FORMAT_W(9)"%" "9" "l" "u" " [ %4.1f%% of total] out of " SIZE_FORMAT_W(9)"%" "9" "l" "u" " bytes [100.0%% used] at " INTPTR_FORMAT"0x%016" "l" "x", |
1195 | name, i, size, size/double(total_size)*100.0, size, p2i(start)); |
1196 | } |
1197 | } |
1198 | |
1199 | void ArchiveBuilder::report_out_of_space(const char* name, size_t needed_bytes) { |
1200 | // This is highly unlikely to happen on 64-bits because we have reserved a 4GB space. |
1201 | // On 32-bit we reserve only 256MB so you could run out of space with 100,000 classes |
1202 | // or so. |
1203 | _rw_region.print_out_of_space_msg(name, needed_bytes); |
1204 | _ro_region.print_out_of_space_msg(name, needed_bytes); |
1205 | |
1206 | vm_exit_during_initialization(err_msg("Unable to allocate from '%s' region", name), |
1207 | "Please reduce the number of shared classes."); |
1208 | } |
1209 | |
1210 | |
1211 | #ifndef PRODUCT |
1212 | void ArchiveBuilder::assert_is_vm_thread() { |
1213 | assert(Thread::current()->is_VM_thread(), "ArchiveBuilder should be used only inside the VMThread")do { if (!(Thread::current()->is_VM_thread())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/cds/archiveBuilder.cpp" , 1213, "assert(" "Thread::current()->is_VM_thread()" ") failed" , "ArchiveBuilder should be used only inside the VMThread"); :: breakpoint(); } } while (0); |
1214 | } |
1215 | #endif |