author | iklam |
Fri, 22 Nov 2019 14:48:40 -0800 | |
changeset 59234 | ee0030a2a306 |
parent 59070 | 22ee476cc664 |
permissions | -rw-r--r-- |
54927 | 1 |
/* |
2 |
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. |
|
3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. |
|
8 |
* |
|
9 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
13 |
* accompanied this code). |
|
14 |
* |
|
15 |
* You should have received a copy of the GNU General Public License version |
|
16 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
17 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 |
* |
|
19 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
20 |
* or visit www.oracle.com if you need additional information or have any |
|
21 |
* questions. |
|
22 |
* |
|
23 |
*/ |
|
24 |
||
25 |
#include "precompiled.hpp" |
|
26 |
#include "jvm.h" |
|
27 |
#include "classfile/classLoaderData.inline.hpp" |
|
28 |
#include "classfile/symbolTable.hpp" |
|
29 |
#include "classfile/systemDictionary.hpp" |
|
30 |
#include "classfile/systemDictionaryShared.hpp" |
|
31 |
#include "logging/log.hpp" |
|
59070
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
32 |
#include "memory/archiveUtils.inline.hpp" |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
33 |
#include "memory/dynamicArchive.hpp" |
54927 | 34 |
#include "memory/metadataFactory.hpp" |
35 |
#include "memory/metaspace.hpp" |
|
36 |
#include "memory/metaspaceClosure.hpp" |
|
37 |
#include "memory/metaspaceShared.hpp" |
|
38 |
#include "memory/resourceArea.hpp" |
|
39 |
#include "oops/compressedOops.hpp" |
|
40 |
#include "oops/objArrayKlass.hpp" |
|
41 |
#include "prims/jvmtiRedefineClasses.hpp" |
|
42 |
#include "runtime/handles.inline.hpp" |
|
43 |
#include "runtime/os.inline.hpp" |
|
44 |
#include "runtime/sharedRuntime.hpp" |
|
45 |
#include "runtime/vmThread.hpp" |
|
46 |
#include "runtime/vmOperations.hpp" |
|
47 |
#include "utilities/bitMap.inline.hpp" |
|
48 |
||
49 |
#ifndef O_BINARY // if defined (Win32) use binary files. |
|
50 |
#define O_BINARY 0 // otherwise do nothing. |
|
51 |
#endif |
|
52 |
||
53 |
class DynamicArchiveBuilder : ResourceObj { |
|
54 |
static unsigned my_hash(const address& a) { |
|
55 |
return primitive_hash<address>(a); |
|
56 |
} |
|
57 |
static bool my_equals(const address& a0, const address& a1) { |
|
58 |
return primitive_equals<address>(a0, a1); |
|
59 |
} |
|
60 |
typedef ResourceHashtable< |
|
61 |
address, address, |
|
62 |
DynamicArchiveBuilder::my_hash, // solaris compiler doesn't like: primitive_hash<address> |
|
63 |
DynamicArchiveBuilder::my_equals, // solaris compiler doesn't like: primitive_equals<address> |
|
64 |
16384, ResourceObj::C_HEAP> RelocationTable; |
|
65 |
RelocationTable _new_loc_table; |
|
66 |
||
59070
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
67 |
static intx _buffer_to_target_delta; |
54927 | 68 |
|
69 |
DumpRegion* _current_dump_space; |
|
70 |
||
71 |
static size_t reserve_alignment() { |
|
72 |
return Metaspace::reserve_alignment(); |
|
73 |
} |
|
74 |
||
75 |
static const int _total_dump_regions = 3; |
|
76 |
int _num_dump_regions_used; |
|
77 |
||
78 |
public: |
|
79 |
void mark_pointer(address* ptr_loc) { |
|
59070
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
80 |
ArchivePtrMarker::mark_pointer(ptr_loc); |
54927 | 81 |
} |
82 |
||
83 |
DumpRegion* current_dump_space() const { |
|
84 |
return _current_dump_space; |
|
85 |
} |
|
86 |
||
87 |
bool is_in_buffer_space(address p) const { |
|
88 |
return (_alloc_bottom <= p && p < (address)current_dump_space()->top()); |
|
89 |
} |
|
90 |
||
91 |
template <typename T> bool is_in_target_space(T target_obj) const { |
|
92 |
address buff_obj = address(target_obj) - _buffer_to_target_delta; |
|
93 |
return is_in_buffer_space(buff_obj); |
|
94 |
} |
|
95 |
||
96 |
template <typename T> bool is_in_buffer_space(T obj) const { |
|
97 |
return is_in_buffer_space(address(obj)); |
|
98 |
} |
|
99 |
||
100 |
template <typename T> T to_target_no_check(T obj) const { |
|
101 |
return (T)(address(obj) + _buffer_to_target_delta); |
|
102 |
} |
|
103 |
||
104 |
template <typename T> T to_target(T obj) const { |
|
105 |
assert(is_in_buffer_space(obj), "must be"); |
|
106 |
return (T)(address(obj) + _buffer_to_target_delta); |
|
107 |
} |
|
108 |
||
109 |
template <typename T> T get_new_loc(T obj) { |
|
110 |
address* pp = _new_loc_table.get((address)obj); |
|
111 |
if (pp == NULL) { |
|
112 |
// Excluded klasses are not copied |
|
113 |
return NULL; |
|
114 |
} else { |
|
115 |
return (T)*pp; |
|
116 |
} |
|
117 |
} |
|
118 |
||
119 |
address get_new_loc(MetaspaceClosure::Ref* ref) { |
|
120 |
return get_new_loc(ref->obj()); |
|
121 |
} |
|
122 |
||
123 |
template <typename T> bool has_new_loc(T obj) { |
|
124 |
address* pp = _new_loc_table.get((address)obj); |
|
125 |
return pp != NULL; |
|
126 |
} |
|
127 |
||
59070
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
128 |
static int dynamic_dump_method_comparator(Method* a, Method* b) { |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
129 |
Symbol* a_name = a->name(); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
130 |
Symbol* b_name = b->name(); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
131 |
|
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
132 |
if (a_name == b_name) { |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
133 |
return 0; |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
134 |
} |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
135 |
|
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
136 |
if (!MetaspaceShared::is_in_shared_metaspace(a_name)) { |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
137 |
// a_name points to a Symbol in the top archive. |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
138 |
// When this method is called, a_name is still pointing to the output space. |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
139 |
// Translate it to point to the output space, so that it can be compared with |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
140 |
// Symbols in the base archive. |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
141 |
a_name = (Symbol*)(address(a_name) + _buffer_to_target_delta); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
142 |
} |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
143 |
if (!MetaspaceShared::is_in_shared_metaspace(b_name)) { |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
144 |
b_name = (Symbol*)(address(b_name) + _buffer_to_target_delta); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
145 |
} |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
146 |
|
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
147 |
return a_name->fast_compare(b_name); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
148 |
} |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
149 |
|
54927 | 150 |
protected: |
151 |
enum FollowMode { |
|
152 |
make_a_copy, point_to_it, set_to_null |
|
153 |
}; |
|
154 |
||
155 |
public: |
|
156 |
void copy(MetaspaceClosure::Ref* ref, bool read_only) { |
|
157 |
int bytes = ref->size() * BytesPerWord; |
|
158 |
address old_obj = ref->obj(); |
|
159 |
address new_obj = copy_impl(ref, read_only, bytes); |
|
160 |
||
161 |
assert(new_obj != NULL, "must be"); |
|
162 |
assert(new_obj != old_obj, "must be"); |
|
163 |
bool isnew = _new_loc_table.put(old_obj, new_obj); |
|
164 |
assert(isnew, "must be"); |
|
165 |
} |
|
166 |
||
167 |
// Make a shallow copy of each eligible MetaspaceObj into the buffer. |
|
168 |
class ShallowCopier: public UniqueMetaspaceClosure { |
|
169 |
DynamicArchiveBuilder* _builder; |
|
170 |
bool _read_only; |
|
171 |
public: |
|
172 |
ShallowCopier(DynamicArchiveBuilder* shuffler, bool read_only) |
|
173 |
: _builder(shuffler), _read_only(read_only) {} |
|
174 |
||
175 |
virtual bool do_unique_ref(Ref* orig_obj, bool read_only) { |
|
176 |
// This method gets called on each *original* object |
|
177 |
// reachable from _builder->iterate_roots(). Each orig_obj is |
|
178 |
// called exactly once. |
|
179 |
FollowMode mode = _builder->follow_ref(orig_obj); |
|
180 |
||
181 |
if (mode == point_to_it) { |
|
182 |
if (read_only == _read_only) { |
|
183 |
log_debug(cds, dynamic)("ptr : " PTR_FORMAT " %s", p2i(orig_obj->obj()), |
|
184 |
MetaspaceObj::type_name(orig_obj->msotype())); |
|
185 |
address p = orig_obj->obj(); |
|
186 |
bool isnew = _builder->_new_loc_table.put(p, p); |
|
187 |
assert(isnew, "must be"); |
|
188 |
} |
|
189 |
return false; |
|
190 |
} |
|
191 |
||
192 |
if (mode == set_to_null) { |
|
193 |
log_debug(cds, dynamic)("nul : " PTR_FORMAT " %s", p2i(orig_obj->obj()), |
|
194 |
MetaspaceObj::type_name(orig_obj->msotype())); |
|
195 |
return false; |
|
196 |
} |
|
197 |
||
198 |
if (read_only == _read_only) { |
|
199 |
// Make a shallow copy of orig_obj in a buffer (maintained |
|
200 |
// by copy_impl in a subclass of DynamicArchiveBuilder). |
|
201 |
_builder->copy(orig_obj, read_only); |
|
202 |
} |
|
203 |
return true; |
|
204 |
} |
|
205 |
}; |
|
206 |
||
207 |
// Relocate all embedded pointer fields within a MetaspaceObj's shallow copy |
|
208 |
class ShallowCopyEmbeddedRefRelocator: public UniqueMetaspaceClosure { |
|
209 |
DynamicArchiveBuilder* _builder; |
|
210 |
public: |
|
211 |
ShallowCopyEmbeddedRefRelocator(DynamicArchiveBuilder* shuffler) |
|
212 |
: _builder(shuffler) {} |
|
213 |
||
214 |
// This method gets called on each *original* object reachable |
|
215 |
// from _builder->iterate_roots(). Each orig_obj is |
|
216 |
// called exactly once. |
|
217 |
virtual bool do_unique_ref(Ref* orig_ref, bool read_only) { |
|
218 |
FollowMode mode = _builder->follow_ref(orig_ref); |
|
219 |
||
220 |
if (mode == point_to_it) { |
|
221 |
// We did not make a copy of this object |
|
222 |
// and we have nothing to update |
|
223 |
assert(_builder->get_new_loc(orig_ref) == NULL || |
|
224 |
_builder->get_new_loc(orig_ref) == orig_ref->obj(), "must be"); |
|
225 |
return false; |
|
226 |
} |
|
227 |
||
228 |
if (mode == set_to_null) { |
|
229 |
// We did not make a copy of this object |
|
230 |
// and we have nothing to update |
|
231 |
assert(!_builder->has_new_loc(orig_ref->obj()), "must not be copied or pointed to"); |
|
232 |
return false; |
|
233 |
} |
|
234 |
||
235 |
// - orig_obj points to the original object. |
|
236 |
// - new_obj points to the shallow copy (created by ShallowCopier) |
|
237 |
// of orig_obj. new_obj is NULL if the orig_obj is excluded |
|
238 |
address orig_obj = orig_ref->obj(); |
|
239 |
address new_obj = _builder->get_new_loc(orig_ref); |
|
240 |
||
241 |
assert(new_obj != orig_obj, "must be"); |
|
242 |
#ifdef ASSERT |
|
243 |
if (new_obj == NULL) { |
|
244 |
if (orig_ref->msotype() == MetaspaceObj::ClassType) { |
|
245 |
Klass* k = (Klass*)orig_obj; |
|
246 |
assert(k->is_instance_klass() && |
|
247 |
SystemDictionaryShared::is_excluded_class(InstanceKlass::cast(k)), |
|
248 |
"orig_obj must be excluded Class"); |
|
249 |
} |
|
250 |
} |
|
251 |
#endif |
|
252 |
||
253 |
log_debug(cds, dynamic)("Relocating " PTR_FORMAT " %s", p2i(new_obj), |
|
254 |
MetaspaceObj::type_name(orig_ref->msotype())); |
|
255 |
if (new_obj != NULL) { |
|
256 |
EmbeddedRefUpdater updater(_builder, orig_obj, new_obj); |
|
257 |
orig_ref->metaspace_pointers_do(&updater); |
|
258 |
} |
|
259 |
||
260 |
return true; // keep recursing until every object is visited exactly once. |
|
261 |
} |
|
59070
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
262 |
|
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
263 |
virtual void push_special(SpecialRef type, Ref* ref, intptr_t* p) { |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
264 |
assert(type == _method_entry_ref, "only special type allowed for now"); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
265 |
address obj = ref->obj(); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
266 |
address new_obj = _builder->get_new_loc(ref); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
267 |
size_t offset = pointer_delta(p, obj, sizeof(u1)); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
268 |
intptr_t* new_p = (intptr_t*)(new_obj + offset); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
269 |
assert(*p == *new_p, "must be a copy"); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
270 |
ArchivePtrMarker::mark_pointer((address*)new_p); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
271 |
} |
54927 | 272 |
}; |
273 |
||
274 |
class EmbeddedRefUpdater: public MetaspaceClosure { |
|
275 |
DynamicArchiveBuilder* _builder; |
|
276 |
address _orig_obj; |
|
277 |
address _new_obj; |
|
278 |
public: |
|
279 |
EmbeddedRefUpdater(DynamicArchiveBuilder* shuffler, address orig_obj, address new_obj) : |
|
280 |
_builder(shuffler), _orig_obj(orig_obj), _new_obj(new_obj) {} |
|
281 |
||
282 |
// This method gets called once for each pointer field F of orig_obj. |
|
283 |
// We update new_obj->F to point to the new location of orig_obj->F. |
|
284 |
// |
|
285 |
// Example: Klass* 0x100 is copied to 0x400 |
|
286 |
// Symbol* 0x200 is copied to 0x500 |
|
287 |
// |
|
288 |
// Let orig_obj == 0x100; and |
|
289 |
// new_obj == 0x400; and |
|
290 |
// ((Klass*)orig_obj)->_name == 0x200; |
|
291 |
// Then this function effectively assigns |
|
292 |
// ((Klass*)new_obj)->_name = 0x500; |
|
293 |
virtual bool do_ref(Ref* ref, bool read_only) { |
|
294 |
address new_pointee = NULL; |
|
295 |
||
296 |
if (ref->not_null()) { |
|
297 |
address old_pointee = ref->obj(); |
|
298 |
||
299 |
FollowMode mode = _builder->follow_ref(ref); |
|
300 |
if (mode == point_to_it) { |
|
301 |
new_pointee = old_pointee; |
|
302 |
} else if (mode == set_to_null) { |
|
303 |
new_pointee = NULL; |
|
304 |
} else { |
|
305 |
new_pointee = _builder->get_new_loc(old_pointee); |
|
306 |
} |
|
307 |
} |
|
308 |
||
309 |
const char* kind = MetaspaceObj::type_name(ref->msotype()); |
|
310 |
// offset of this field inside the original object |
|
311 |
intx offset = (address)ref->addr() - _orig_obj; |
|
312 |
_builder->update_pointer((address*)(_new_obj + offset), new_pointee, kind, offset); |
|
313 |
||
314 |
// We can't mark the pointer here, because DynamicArchiveBuilder::sort_methods |
|
315 |
// may re-layout the [iv]tables, which would change the offset(s) in an InstanceKlass |
|
316 |
// that would contain pointers. Therefore, we must mark the pointers after |
|
317 |
// sort_methods(), using PointerMarker. |
|
318 |
return false; // Do not recurse. |
|
319 |
} |
|
320 |
}; |
|
321 |
||
322 |
class ExternalRefUpdater: public MetaspaceClosure { |
|
323 |
DynamicArchiveBuilder* _builder; |
|
324 |
||
325 |
public: |
|
326 |
ExternalRefUpdater(DynamicArchiveBuilder* shuffler) : _builder(shuffler) {} |
|
327 |
||
328 |
virtual bool do_ref(Ref* ref, bool read_only) { |
|
329 |
// ref is a pointer that lives OUTSIDE of the buffer, but points to an object inside the buffer |
|
330 |
if (ref->not_null()) { |
|
331 |
address new_loc = _builder->get_new_loc(ref); |
|
332 |
const char* kind = MetaspaceObj::type_name(ref->msotype()); |
|
333 |
_builder->update_pointer(ref->addr(), new_loc, kind, 0); |
|
334 |
_builder->mark_pointer(ref->addr()); |
|
335 |
} |
|
336 |
return false; // Do not recurse. |
|
337 |
} |
|
338 |
}; |
|
339 |
||
340 |
class PointerMarker: public UniqueMetaspaceClosure { |
|
341 |
DynamicArchiveBuilder* _builder; |
|
342 |
||
343 |
public: |
|
344 |
PointerMarker(DynamicArchiveBuilder* shuffler) : _builder(shuffler) {} |
|
345 |
||
346 |
virtual bool do_unique_ref(Ref* ref, bool read_only) { |
|
347 |
if (_builder->is_in_buffer_space(ref->obj())) { |
|
348 |
EmbeddedRefMarker ref_marker(_builder); |
|
349 |
ref->metaspace_pointers_do(&ref_marker); |
|
350 |
return true; // keep recursing until every buffered object is visited exactly once. |
|
351 |
} else { |
|
352 |
return false; |
|
353 |
} |
|
354 |
} |
|
355 |
}; |
|
356 |
||
357 |
class EmbeddedRefMarker: public MetaspaceClosure { |
|
358 |
DynamicArchiveBuilder* _builder; |
|
359 |
||
360 |
public: |
|
361 |
EmbeddedRefMarker(DynamicArchiveBuilder* shuffler) : _builder(shuffler) {} |
|
362 |
virtual bool do_ref(Ref* ref, bool read_only) { |
|
59070
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
363 |
if (ref->not_null()) { |
54927 | 364 |
_builder->mark_pointer(ref->addr()); |
365 |
} |
|
366 |
return false; // Do not recurse. |
|
367 |
} |
|
368 |
}; |
|
369 |
||
370 |
void update_pointer(address* addr, address value, const char* kind, uintx offset, bool is_mso_pointer=true) { |
|
371 |
// Propagate the the mask bits to the new value -- see comments above MetaspaceClosure::obj() |
|
372 |
if (is_mso_pointer) { |
|
373 |
const uintx FLAG_MASK = 0x03; |
|
374 |
uintx mask_bits = uintx(*addr) & FLAG_MASK; |
|
375 |
value = (address)(uintx(value) | mask_bits); |
|
376 |
} |
|
377 |
||
378 |
if (*addr != value) { |
|
379 |
log_debug(cds, dynamic)("Update (%18s*) %3d [" PTR_FORMAT "] " PTR_FORMAT " -> " PTR_FORMAT, |
|
380 |
kind, int(offset), p2i(addr), p2i(*addr), p2i(value)); |
|
381 |
*addr = value; |
|
382 |
} |
|
383 |
} |
|
384 |
||
385 |
private: |
|
386 |
GrowableArray<Symbol*>* _symbols; // symbols to dump |
|
387 |
GrowableArray<InstanceKlass*>* _klasses; // klasses to dump |
|
388 |
||
389 |
void append(InstanceKlass* k) { _klasses->append(k); } |
|
390 |
void append(Symbol* s) { _symbols->append(s); } |
|
391 |
||
392 |
class GatherKlassesAndSymbols : public UniqueMetaspaceClosure { |
|
393 |
DynamicArchiveBuilder* _builder; |
|
394 |
bool _read_only; |
|
395 |
||
396 |
public: |
|
397 |
GatherKlassesAndSymbols(DynamicArchiveBuilder* builder) |
|
398 |
: _builder(builder) {} |
|
399 |
||
400 |
virtual bool do_unique_ref(Ref* ref, bool read_only) { |
|
401 |
if (_builder->follow_ref(ref) != make_a_copy) { |
|
402 |
return false; |
|
403 |
} |
|
404 |
if (ref->msotype() == MetaspaceObj::ClassType) { |
|
405 |
Klass* klass = (Klass*)ref->obj(); |
|
406 |
assert(klass->is_klass(), "must be"); |
|
407 |
if (klass->is_instance_klass()) { |
|
408 |
InstanceKlass* ik = InstanceKlass::cast(klass); |
|
409 |
assert(!SystemDictionaryShared::is_excluded_class(ik), "must be"); |
|
410 |
_builder->append(ik); |
|
411 |
_builder->_estimated_metsapceobj_bytes += BytesPerWord; // See RunTimeSharedClassInfo::get_for() |
|
412 |
} |
|
413 |
} else if (ref->msotype() == MetaspaceObj::SymbolType) { |
|
414 |
_builder->append((Symbol*)ref->obj()); |
|
415 |
} |
|
416 |
||
417 |
int bytes = ref->size() * BytesPerWord; |
|
418 |
_builder->_estimated_metsapceobj_bytes += bytes; |
|
419 |
||
420 |
return true; |
|
421 |
} |
|
422 |
}; |
|
423 |
||
424 |
FollowMode follow_ref(MetaspaceClosure::Ref *ref) { |
|
425 |
address obj = ref->obj(); |
|
426 |
if (MetaspaceShared::is_in_shared_metaspace(obj)) { |
|
427 |
// Don't dump existing shared metadata again. |
|
428 |
return point_to_it; |
|
429 |
} else if (ref->msotype() == MetaspaceObj::MethodDataType) { |
|
430 |
return set_to_null; |
|
431 |
} else { |
|
432 |
if (ref->msotype() == MetaspaceObj::ClassType) { |
|
433 |
Klass* klass = (Klass*)ref->obj(); |
|
434 |
assert(klass->is_klass(), "must be"); |
|
435 |
if (klass->is_instance_klass()) { |
|
436 |
InstanceKlass* ik = InstanceKlass::cast(klass); |
|
437 |
if (SystemDictionaryShared::is_excluded_class(ik)) { |
|
438 |
ResourceMark rm; |
|
439 |
log_debug(cds, dynamic)("Skipping class (excluded): %s", klass->external_name()); |
|
440 |
return set_to_null; |
|
441 |
} |
|
442 |
} else if (klass->is_array_klass()) { |
|
443 |
// Don't support archiving of array klasses for now. |
|
444 |
ResourceMark rm; |
|
445 |
log_debug(cds, dynamic)("Skipping class (array): %s", klass->external_name()); |
|
446 |
return set_to_null; |
|
447 |
} |
|
448 |
} |
|
449 |
||
450 |
return make_a_copy; |
|
451 |
} |
|
452 |
} |
|
453 |
||
454 |
address copy_impl(MetaspaceClosure::Ref* ref, bool read_only, int bytes) { |
|
455 |
if (ref->msotype() == MetaspaceObj::ClassType) { |
|
456 |
// Save a pointer immediate in front of an InstanceKlass, so |
|
457 |
// we can do a quick lookup from InstanceKlass* -> RunTimeSharedClassInfo* |
|
458 |
// without building another hashtable. See RunTimeSharedClassInfo::get_for() |
|
459 |
// in systemDictionaryShared.cpp. |
|
460 |
address obj = ref->obj(); |
|
461 |
Klass* klass = (Klass*)obj; |
|
462 |
if (klass->is_instance_klass()) { |
|
463 |
SystemDictionaryShared::validate_before_archiving(InstanceKlass::cast(klass)); |
|
464 |
current_dump_space()->allocate(sizeof(address), BytesPerWord); |
|
465 |
} |
|
466 |
} |
|
467 |
address p = (address)current_dump_space()->allocate(bytes); |
|
468 |
address obj = ref->obj(); |
|
469 |
log_debug(cds, dynamic)("COPY: " PTR_FORMAT " ==> " PTR_FORMAT " %5d %s", |
|
470 |
p2i(obj), p2i(p), bytes, |
|
471 |
MetaspaceObj::type_name(ref->msotype())); |
|
472 |
memcpy(p, obj, bytes); |
|
473 |
intptr_t* cloned_vtable = MetaspaceShared::fix_cpp_vtable_for_dynamic_archive(ref->msotype(), p); |
|
474 |
if (cloned_vtable != NULL) { |
|
475 |
update_pointer((address*)p, (address)cloned_vtable, "vtb", 0, /*is_mso_pointer*/false); |
|
59070
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
476 |
mark_pointer((address*)p); |
54927 | 477 |
} |
478 |
||
479 |
return (address)p; |
|
480 |
} |
|
481 |
||
482 |
DynamicArchiveHeader *_header; |
|
483 |
address _alloc_bottom; |
|
484 |
address _last_verified_top; |
|
485 |
size_t _other_region_used_bytes; |
|
486 |
||
487 |
// Conservative estimate for number of bytes needed for: |
|
488 |
size_t _estimated_metsapceobj_bytes; // all archived MetsapceObj's. |
|
489 |
size_t _estimated_hashtable_bytes; // symbol table and dictionaries |
|
490 |
size_t _estimated_trampoline_bytes; // method entry trampolines |
|
491 |
||
492 |
size_t estimate_archive_size(); |
|
493 |
size_t estimate_trampoline_size(); |
|
494 |
size_t estimate_class_file_size(); |
|
495 |
address reserve_space_and_init_buffer_to_target_delta(); |
|
496 |
void init_header(address addr); |
|
59234
ee0030a2a306
8234429: appcds/dynamicArchive tests crashing with Graal
iklam
parents:
59070
diff
changeset
|
497 |
void release_header(); |
54927 | 498 |
void make_trampolines(); |
499 |
void make_klasses_shareable(); |
|
500 |
void sort_methods(InstanceKlass* ik) const; |
|
501 |
void set_symbols_permanent(); |
|
502 |
void relocate_buffer_to_target(); |
|
58278
e47b459b315c
8231278: Rename FileMapHeader::_read_only_tables_start to _serialized_data_start
iklam
parents:
58277
diff
changeset
|
503 |
void write_archive(char* serialized_data_start); |
58277
00a98f0aa1b3
8231257: Avoid calling FileMapInfo::write_region twice
iklam
parents:
58096
diff
changeset
|
504 |
void write_regions(FileMapInfo* dynamic_info); |
54927 | 505 |
|
506 |
void init_first_dump_space(address reserved_bottom) { |
|
507 |
address first_space_base = reserved_bottom; |
|
508 |
DumpRegion* rw_space = MetaspaceShared::read_write_dump_space(); |
|
509 |
MetaspaceShared::init_shared_dump_space(rw_space, first_space_base); |
|
510 |
_current_dump_space = rw_space; |
|
511 |
_last_verified_top = first_space_base; |
|
512 |
_num_dump_regions_used = 1; |
|
513 |
} |
|
514 |
||
515 |
public: |
|
516 |
DynamicArchiveBuilder() { |
|
517 |
_klasses = new (ResourceObj::C_HEAP, mtClass) GrowableArray<InstanceKlass*>(100, true, mtInternal); |
|
518 |
_symbols = new (ResourceObj::C_HEAP, mtClass) GrowableArray<Symbol*>(1000, true, mtInternal); |
|
519 |
||
520 |
_estimated_metsapceobj_bytes = 0; |
|
521 |
_estimated_hashtable_bytes = 0; |
|
522 |
_estimated_trampoline_bytes = 0; |
|
523 |
||
524 |
_num_dump_regions_used = 0; |
|
525 |
} |
|
526 |
||
527 |
void start_dump_space(DumpRegion* next) { |
|
528 |
address bottom = _last_verified_top; |
|
529 |
address top = (address)(current_dump_space()->top()); |
|
530 |
_other_region_used_bytes += size_t(top - bottom); |
|
531 |
||
532 |
MetaspaceShared::pack_dump_space(current_dump_space(), next, MetaspaceShared::shared_rs()); |
|
533 |
_current_dump_space = next; |
|
534 |
_num_dump_regions_used ++; |
|
535 |
||
536 |
_last_verified_top = (address)(current_dump_space()->top()); |
|
537 |
} |
|
538 |
||
539 |
void verify_estimate_size(size_t estimate, const char* which) { |
|
540 |
address bottom = _last_verified_top; |
|
541 |
address top = (address)(current_dump_space()->top()); |
|
542 |
size_t used = size_t(top - bottom) + _other_region_used_bytes; |
|
543 |
int diff = int(estimate) - int(used); |
|
544 |
||
54932
0f934da77390
8224170: Build failures after JDK-8207812 (Implement Dynamic CDS Archive)
shade
parents:
54927
diff
changeset
|
545 |
log_info(cds)("%s estimate = " SIZE_FORMAT " used = " SIZE_FORMAT "; diff = %d bytes", which, estimate, used, diff); |
54927 | 546 |
assert(diff >= 0, "Estimate is too small"); |
547 |
||
548 |
_last_verified_top = top; |
|
549 |
_other_region_used_bytes = 0; |
|
550 |
} |
|
551 |
||
552 |
// Do this before and after the archive dump to see if any corruption |
|
553 |
// is caused by dynamic dumping. |
|
554 |
void verify_universe(const char* info) { |
|
555 |
if (VerifyBeforeExit) { |
|
556 |
log_info(cds)("Verify %s", info); |
|
557 |
HandleMark hm; |
|
558 |
// Among other things, this ensures that Eden top is correct. |
|
559 |
Universe::heap()->prepare_for_verify(); |
|
560 |
Universe::verify(info); |
|
561 |
} |
|
562 |
} |
|
563 |
||
564 |
void doit() { |
|
565 |
verify_universe("Before CDS dynamic dump"); |
|
566 |
DEBUG_ONLY(SystemDictionaryShared::NoClassLoadingMark nclm); |
|
567 |
SystemDictionaryShared::check_excluded_classes(); |
|
568 |
||
569 |
{ |
|
570 |
ResourceMark rm; |
|
571 |
GatherKlassesAndSymbols gatherer(this); |
|
572 |
||
573 |
SystemDictionaryShared::dumptime_classes_do(&gatherer); |
|
574 |
SymbolTable::metaspace_pointers_do(&gatherer); |
|
575 |
FileMapInfo::metaspace_pointers_do(&gatherer); |
|
576 |
||
577 |
gatherer.finish(); |
|
578 |
} |
|
579 |
||
580 |
// rw space starts ... |
|
581 |
address reserved_bottom = reserve_space_and_init_buffer_to_target_delta(); |
|
582 |
init_header(reserved_bottom); |
|
583 |
||
59070
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
584 |
CHeapBitMap ptrmap; |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
585 |
ArchivePtrMarker::initialize(&ptrmap, (address*)reserved_bottom, (address*)current_dump_space()->top()); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
586 |
|
54927 | 587 |
verify_estimate_size(sizeof(DynamicArchiveHeader), "header"); |
588 |
||
589 |
log_info(cds, dynamic)("Copying %d klasses and %d symbols", |
|
590 |
_klasses->length(), _symbols->length()); |
|
591 |
||
592 |
{ |
|
593 |
assert(current_dump_space() == MetaspaceShared::read_write_dump_space(), |
|
594 |
"Current dump space is not rw space"); |
|
595 |
// shallow-copy RW objects, if necessary |
|
596 |
ResourceMark rm; |
|
597 |
ShallowCopier rw_copier(this, false); |
|
598 |
iterate_roots(&rw_copier); |
|
599 |
} |
|
600 |
||
601 |
// ro space starts ... |
|
602 |
DumpRegion* ro_space = MetaspaceShared::read_only_dump_space(); |
|
603 |
{ |
|
604 |
start_dump_space(ro_space); |
|
605 |
||
606 |
// shallow-copy RO objects, if necessary |
|
607 |
ResourceMark rm; |
|
608 |
ShallowCopier ro_copier(this, true); |
|
609 |
iterate_roots(&ro_copier); |
|
610 |
} |
|
611 |
||
612 |
{ |
|
613 |
log_info(cds)("Relocating embedded pointers ... "); |
|
614 |
ResourceMark rm; |
|
615 |
ShallowCopyEmbeddedRefRelocator emb_reloc(this); |
|
616 |
iterate_roots(&emb_reloc); |
|
617 |
} |
|
618 |
||
619 |
{ |
|
620 |
log_info(cds)("Relocating external roots ... "); |
|
621 |
ResourceMark rm; |
|
622 |
ExternalRefUpdater ext_reloc(this); |
|
623 |
iterate_roots(&ext_reloc); |
|
624 |
} |
|
625 |
||
626 |
verify_estimate_size(_estimated_metsapceobj_bytes, "MetaspaceObjs"); |
|
627 |
||
58278
e47b459b315c
8231278: Rename FileMapHeader::_read_only_tables_start to _serialized_data_start
iklam
parents:
58277
diff
changeset
|
628 |
char* serialized_data_start; |
54927 | 629 |
{ |
630 |
set_symbols_permanent(); |
|
631 |
||
632 |
// Write the symbol table and system dictionaries to the RO space. |
|
633 |
// Note that these tables still point to the *original* objects |
|
634 |
// (because they were not processed by ExternalRefUpdater), so |
|
635 |
// they would need to call DynamicArchive::original_to_target() to |
|
636 |
// get the correct addresses. |
|
637 |
assert(current_dump_space() == ro_space, "Must be RO space"); |
|
638 |
SymbolTable::write_to_archive(false); |
|
639 |
SystemDictionaryShared::write_to_archive(false); |
|
640 |
||
58278
e47b459b315c
8231278: Rename FileMapHeader::_read_only_tables_start to _serialized_data_start
iklam
parents:
58277
diff
changeset
|
641 |
serialized_data_start = ro_space->top(); |
54927 | 642 |
WriteClosure wc(ro_space); |
643 |
SymbolTable::serialize_shared_table_header(&wc, false); |
|
644 |
SystemDictionaryShared::serialize_dictionary_headers(&wc, false); |
|
645 |
} |
|
646 |
||
647 |
verify_estimate_size(_estimated_hashtable_bytes, "Hashtables"); |
|
648 |
||
649 |
// mc space starts ... |
|
650 |
{ |
|
651 |
start_dump_space(MetaspaceShared::misc_code_dump_space()); |
|
652 |
make_trampolines(); |
|
653 |
} |
|
654 |
||
655 |
verify_estimate_size(_estimated_trampoline_bytes, "Trampolines"); |
|
656 |
||
657 |
make_klasses_shareable(); |
|
658 |
||
659 |
{ |
|
660 |
log_info(cds)("Final relocation of pointers ... "); |
|
661 |
ResourceMark rm; |
|
662 |
PointerMarker marker(this); |
|
663 |
iterate_roots(&marker); |
|
664 |
relocate_buffer_to_target(); |
|
665 |
} |
|
666 |
||
58278
e47b459b315c
8231278: Rename FileMapHeader::_read_only_tables_start to _serialized_data_start
iklam
parents:
58277
diff
changeset
|
667 |
write_archive(serialized_data_start); |
59234
ee0030a2a306
8234429: appcds/dynamicArchive tests crashing with Graal
iklam
parents:
59070
diff
changeset
|
668 |
release_header(); |
54927 | 669 |
|
670 |
assert(_num_dump_regions_used == _total_dump_regions, "must be"); |
|
671 |
verify_universe("After CDS dynamic dump"); |
|
672 |
} |
|
673 |
||
674 |
void iterate_roots(MetaspaceClosure* it) { |
|
675 |
int i; |
|
676 |
int num_klasses = _klasses->length(); |
|
677 |
for (i = 0; i < num_klasses; i++) { |
|
678 |
it->push(&_klasses->at(i)); |
|
679 |
} |
|
680 |
||
681 |
int num_symbols = _symbols->length(); |
|
682 |
for (i = 0; i < num_symbols; i++) { |
|
683 |
it->push(&_symbols->at(i)); |
|
684 |
} |
|
685 |
||
59070
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
686 |
FileMapInfo::metaspace_pointers_do(it); |
54927 | 687 |
|
688 |
// Do not call these again, as we have already collected all the classes and symbols |
|
689 |
// that we want to archive. Also, these calls would corrupt the tables when |
|
690 |
// ExternalRefUpdater is used. |
|
691 |
// |
|
692 |
// SystemDictionaryShared::dumptime_classes_do(it); |
|
693 |
// SymbolTable::metaspace_pointers_do(it); |
|
694 |
||
695 |
it->finish(); |
|
696 |
} |
|
697 |
}; |
|
698 |
||
59070
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
699 |
intx DynamicArchiveBuilder::_buffer_to_target_delta; |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
700 |
|
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
701 |
|
54927 | 702 |
size_t DynamicArchiveBuilder::estimate_archive_size() { |
703 |
// size of the symbol table and two dictionaries, plus the RunTimeSharedClassInfo's |
|
704 |
_estimated_hashtable_bytes = 0; |
|
705 |
_estimated_hashtable_bytes += SymbolTable::estimate_size_for_archive(); |
|
706 |
_estimated_hashtable_bytes += SystemDictionaryShared::estimate_size_for_archive(); |
|
707 |
||
708 |
_estimated_trampoline_bytes = estimate_trampoline_size(); |
|
709 |
||
710 |
size_t total = 0; |
|
711 |
||
712 |
total += _estimated_metsapceobj_bytes; |
|
713 |
total += _estimated_hashtable_bytes; |
|
714 |
total += _estimated_trampoline_bytes; |
|
715 |
||
716 |
// allow fragmentation at the end of each dump region |
|
717 |
total += _total_dump_regions * reserve_alignment(); |
|
718 |
||
719 |
return align_up(total, reserve_alignment()); |
|
720 |
} |
|
721 |
||
722 |
address DynamicArchiveBuilder::reserve_space_and_init_buffer_to_target_delta() { |
|
723 |
size_t total = estimate_archive_size(); |
|
59070
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
724 |
ReservedSpace rs = MetaspaceShared::reserve_shared_space(total); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
725 |
if (!rs.is_reserved()) { |
54927 | 726 |
log_error(cds, dynamic)("Failed to reserve %d bytes of output buffer.", (int)total); |
727 |
vm_direct_exit(0); |
|
728 |
} |
|
729 |
||
59070
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
730 |
address buffer_base = (address)rs.base(); |
54927 | 731 |
log_info(cds, dynamic)("Reserved output buffer space at : " PTR_FORMAT " [%d bytes]", |
732 |
p2i(buffer_base), (int)total); |
|
59070
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
733 |
MetaspaceShared::set_shared_rs(rs); |
54927 | 734 |
|
735 |
// At run time, we will mmap the dynamic archive at target_space_bottom. |
|
736 |
// However, at dump time, we may not be able to write into the target_space, |
|
737 |
// as it's occupied by dynamically loaded Klasses. So we allocate a buffer |
|
738 |
// at an arbitrary location chosen by the OS. We will write all the dynamically |
|
739 |
// archived classes into this buffer. At the final stage of dumping, we relocate |
|
740 |
// all pointers that are inside the buffer_space to point to their (runtime) |
|
741 |
// target location inside thetarget_space. |
|
742 |
address target_space_bottom = |
|
743 |
(address)align_up(MetaspaceShared::shared_metaspace_top(), reserve_alignment()); |
|
744 |
_buffer_to_target_delta = intx(target_space_bottom) - intx(buffer_base); |
|
745 |
||
746 |
log_info(cds, dynamic)("Target archive space at : " PTR_FORMAT, p2i(target_space_bottom)); |
|
747 |
log_info(cds, dynamic)("Buffer-space to target-space delta : " PTR_FORMAT, p2i((address)_buffer_to_target_delta)); |
|
748 |
||
749 |
return buffer_base; |
|
750 |
} |
|
751 |
||
752 |
void DynamicArchiveBuilder::init_header(address reserved_bottom) { |
|
753 |
_alloc_bottom = reserved_bottom; |
|
754 |
_last_verified_top = reserved_bottom; |
|
755 |
_other_region_used_bytes = 0; |
|
756 |
||
757 |
init_first_dump_space(reserved_bottom); |
|
758 |
||
759 |
FileMapInfo* mapinfo = new FileMapInfo(false); |
|
59234
ee0030a2a306
8234429: appcds/dynamicArchive tests crashing with Graal
iklam
parents:
59070
diff
changeset
|
760 |
assert(FileMapInfo::dynamic_info() == mapinfo, "must be"); |
58096 | 761 |
_header = mapinfo->dynamic_header(); |
54927 | 762 |
|
763 |
Thread* THREAD = Thread::current(); |
|
764 |
FileMapInfo* base_info = FileMapInfo::current_info(); |
|
58096 | 765 |
_header->set_base_header_crc(base_info->crc()); |
54927 | 766 |
for (int i = 0; i < MetaspaceShared::n_regions; i++) { |
58096 | 767 |
_header->set_base_region_crc(i, base_info->space_crc(i)); |
54927 | 768 |
} |
769 |
_header->populate(base_info, os::vm_allocation_granularity()); |
|
770 |
} |
|
771 |
||
59234
ee0030a2a306
8234429: appcds/dynamicArchive tests crashing with Graal
iklam
parents:
59070
diff
changeset
|
772 |
void DynamicArchiveBuilder::release_header() { |
ee0030a2a306
8234429: appcds/dynamicArchive tests crashing with Graal
iklam
parents:
59070
diff
changeset
|
773 |
// We temporarily allocated a dynamic FileMapInfo for dumping, which makes it appear we |
ee0030a2a306
8234429: appcds/dynamicArchive tests crashing with Graal
iklam
parents:
59070
diff
changeset
|
774 |
// have mapped a dynamic archive, but we actually have not. We are in a safepoint now. |
ee0030a2a306
8234429: appcds/dynamicArchive tests crashing with Graal
iklam
parents:
59070
diff
changeset
|
775 |
// Let's free it so that if class loading happens after we leave the safepoint, nothing |
ee0030a2a306
8234429: appcds/dynamicArchive tests crashing with Graal
iklam
parents:
59070
diff
changeset
|
776 |
// bad will happen. |
ee0030a2a306
8234429: appcds/dynamicArchive tests crashing with Graal
iklam
parents:
59070
diff
changeset
|
777 |
assert(SafepointSynchronize::is_at_safepoint(), "must be"); |
ee0030a2a306
8234429: appcds/dynamicArchive tests crashing with Graal
iklam
parents:
59070
diff
changeset
|
778 |
FileMapInfo *mapinfo = FileMapInfo::dynamic_info(); |
ee0030a2a306
8234429: appcds/dynamicArchive tests crashing with Graal
iklam
parents:
59070
diff
changeset
|
779 |
assert(mapinfo != NULL && _header == mapinfo->dynamic_header(), "must be"); |
ee0030a2a306
8234429: appcds/dynamicArchive tests crashing with Graal
iklam
parents:
59070
diff
changeset
|
780 |
delete mapinfo; |
ee0030a2a306
8234429: appcds/dynamicArchive tests crashing with Graal
iklam
parents:
59070
diff
changeset
|
781 |
assert(!DynamicArchive::is_mapped(), "must be"); |
ee0030a2a306
8234429: appcds/dynamicArchive tests crashing with Graal
iklam
parents:
59070
diff
changeset
|
782 |
_header = NULL; |
ee0030a2a306
8234429: appcds/dynamicArchive tests crashing with Graal
iklam
parents:
59070
diff
changeset
|
783 |
} |
ee0030a2a306
8234429: appcds/dynamicArchive tests crashing with Graal
iklam
parents:
59070
diff
changeset
|
784 |
|
54927 | 785 |
size_t DynamicArchiveBuilder::estimate_trampoline_size() { |
786 |
size_t total = 0; |
|
787 |
size_t each_method_bytes = |
|
788 |
align_up(SharedRuntime::trampoline_size(), BytesPerWord) + |
|
789 |
align_up(sizeof(AdapterHandlerEntry*), BytesPerWord); |
|
790 |
||
791 |
for (int i = 0; i < _klasses->length(); i++) { |
|
792 |
InstanceKlass* ik = _klasses->at(i); |
|
793 |
Array<Method*>* methods = ik->methods(); |
|
794 |
total += each_method_bytes * methods->length(); |
|
795 |
} |
|
55134
72474808e305
8224692: runtime/appcds tests crash in "HotSpotJVMCI::compute_offset" when running in Graal as JIT mode
iklam
parents:
54932
diff
changeset
|
796 |
if (total == 0) { |
72474808e305
8224692: runtime/appcds tests crash in "HotSpotJVMCI::compute_offset" when running in Graal as JIT mode
iklam
parents:
54932
diff
changeset
|
797 |
// We have nothing to archive, but let's avoid having an empty region. |
72474808e305
8224692: runtime/appcds tests crash in "HotSpotJVMCI::compute_offset" when running in Graal as JIT mode
iklam
parents:
54932
diff
changeset
|
798 |
total = SharedRuntime::trampoline_size(); |
72474808e305
8224692: runtime/appcds tests crash in "HotSpotJVMCI::compute_offset" when running in Graal as JIT mode
iklam
parents:
54932
diff
changeset
|
799 |
} |
54927 | 800 |
return total; |
801 |
} |
|
802 |
||
803 |
void DynamicArchiveBuilder::make_trampolines() { |
|
804 |
for (int i = 0; i < _klasses->length(); i++) { |
|
805 |
InstanceKlass* ik = _klasses->at(i); |
|
806 |
Array<Method*>* methods = ik->methods(); |
|
807 |
for (int j = 0; j < methods->length(); j++) { |
|
808 |
Method* m = methods->at(j); |
|
809 |
address c2i_entry_trampoline = |
|
810 |
(address)MetaspaceShared::misc_code_space_alloc(SharedRuntime::trampoline_size()); |
|
811 |
m->set_from_compiled_entry(to_target(c2i_entry_trampoline)); |
|
812 |
AdapterHandlerEntry** adapter_trampoline = |
|
813 |
(AdapterHandlerEntry**)MetaspaceShared::misc_code_space_alloc(sizeof(AdapterHandlerEntry*)); |
|
814 |
*adapter_trampoline = NULL; |
|
815 |
m->set_adapter_trampoline(to_target(adapter_trampoline)); |
|
816 |
} |
|
817 |
} |
|
55134
72474808e305
8224692: runtime/appcds tests crash in "HotSpotJVMCI::compute_offset" when running in Graal as JIT mode
iklam
parents:
54932
diff
changeset
|
818 |
|
72474808e305
8224692: runtime/appcds tests crash in "HotSpotJVMCI::compute_offset" when running in Graal as JIT mode
iklam
parents:
54932
diff
changeset
|
819 |
if (MetaspaceShared::misc_code_dump_space()->used() == 0) { |
72474808e305
8224692: runtime/appcds tests crash in "HotSpotJVMCI::compute_offset" when running in Graal as JIT mode
iklam
parents:
54932
diff
changeset
|
820 |
// We have nothing to archive, but let's avoid having an empty region. |
72474808e305
8224692: runtime/appcds tests crash in "HotSpotJVMCI::compute_offset" when running in Graal as JIT mode
iklam
parents:
54932
diff
changeset
|
821 |
MetaspaceShared::misc_code_space_alloc(SharedRuntime::trampoline_size()); |
72474808e305
8224692: runtime/appcds tests crash in "HotSpotJVMCI::compute_offset" when running in Graal as JIT mode
iklam
parents:
54932
diff
changeset
|
822 |
} |
54927 | 823 |
} |
824 |
||
825 |
void DynamicArchiveBuilder::make_klasses_shareable() { |
|
826 |
int i, count = _klasses->length(); |
|
827 |
||
59070
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
828 |
InstanceKlass::disable_method_binary_search(); |
54927 | 829 |
for (i = 0; i < count; i++) { |
830 |
InstanceKlass* ik = _klasses->at(i); |
|
831 |
sort_methods(ik); |
|
832 |
} |
|
833 |
||
834 |
for (i = 0; i < count; i++) { |
|
835 |
InstanceKlass* ik = _klasses->at(i); |
|
836 |
ClassLoaderData *cld = ik->class_loader_data(); |
|
837 |
if (cld->is_boot_class_loader_data()) { |
|
838 |
ik->set_class_loader_type(ClassLoader::BOOT_LOADER); |
|
839 |
} |
|
840 |
else if (cld->is_platform_class_loader_data()) { |
|
841 |
ik->set_class_loader_type(ClassLoader::PLATFORM_LOADER); |
|
842 |
} |
|
843 |
else if (cld->is_system_class_loader_data()) { |
|
844 |
ik->set_class_loader_type(ClassLoader::APP_LOADER); |
|
845 |
} |
|
846 |
||
59056
15936b142f86
8233913: Remove implicit conversion from Method* to methodHandle
coleenp
parents:
58278
diff
changeset
|
847 |
MetaspaceShared::rewrite_nofast_bytecodes_and_calculate_fingerprints(Thread::current(), ik); |
54927 | 848 |
ik->remove_unshareable_info(); |
849 |
||
850 |
assert(ik->array_klasses() == NULL, "sanity"); |
|
851 |
||
852 |
if (log_is_enabled(Debug, cds, dynamic)) { |
|
853 |
ResourceMark rm; |
|
854 |
log_debug(cds, dynamic)("klasses[%4i] = " PTR_FORMAT " %s", i, p2i(to_target(ik)), ik->external_name()); |
|
855 |
} |
|
856 |
} |
|
857 |
} |
|
858 |
||
859 |
// The address order of the copied Symbols may be different than when the original |
|
860 |
// klasses were created. Re-sort all the tables. See Method::sort_methods(). |
|
861 |
void DynamicArchiveBuilder::sort_methods(InstanceKlass* ik) const { |
|
862 |
assert(ik != NULL, "DynamicArchiveBuilder currently doesn't support dumping the base archive"); |
|
863 |
if (MetaspaceShared::is_in_shared_metaspace(ik)) { |
|
864 |
// We have reached a supertype that's already in the base archive |
|
865 |
return; |
|
866 |
} |
|
867 |
||
868 |
if (ik->java_mirror() == NULL) { |
|
869 |
// NULL mirror means this class has already been visited and methods are already sorted |
|
870 |
return; |
|
871 |
} |
|
872 |
ik->remove_java_mirror(); |
|
873 |
||
874 |
if (log_is_enabled(Debug, cds, dynamic)) { |
|
875 |
ResourceMark rm; |
|
876 |
log_debug(cds, dynamic)("sorting methods for " PTR_FORMAT " %s", p2i(to_target(ik)), ik->external_name()); |
|
877 |
} |
|
878 |
||
879 |
// Make sure all supertypes have been sorted |
|
880 |
sort_methods(ik->java_super()); |
|
881 |
Array<InstanceKlass*>* interfaces = ik->local_interfaces(); |
|
882 |
int len = interfaces->length(); |
|
883 |
for (int i = 0; i < len; i++) { |
|
884 |
sort_methods(interfaces->at(i)); |
|
885 |
} |
|
886 |
||
887 |
#ifdef ASSERT |
|
59070
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
888 |
if (ik->methods() != NULL) { |
54927 | 889 |
for (int m = 0; m < ik->methods()->length(); m++) { |
890 |
Symbol* name = ik->methods()->at(m)->name(); |
|
891 |
assert(MetaspaceShared::is_in_shared_metaspace(name) || is_in_buffer_space(name), "must be"); |
|
892 |
} |
|
893 |
} |
|
59070
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
894 |
if (ik->default_methods() != NULL) { |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
895 |
for (int m = 0; m < ik->default_methods()->length(); m++) { |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
896 |
Symbol* name = ik->default_methods()->at(m)->name(); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
897 |
assert(MetaspaceShared::is_in_shared_metaspace(name) || is_in_buffer_space(name), "must be"); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
898 |
} |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
899 |
} |
54927 | 900 |
#endif |
901 |
||
902 |
Thread* THREAD = Thread::current(); |
|
59070
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
903 |
Method::sort_methods(ik->methods(), /*set_idnums=*/true, dynamic_dump_method_comparator); |
54927 | 904 |
if (ik->default_methods() != NULL) { |
59070
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
905 |
Method::sort_methods(ik->default_methods(), /*set_idnums=*/false, dynamic_dump_method_comparator); |
54927 | 906 |
} |
907 |
ik->vtable().initialize_vtable(true, THREAD); assert(!HAS_PENDING_EXCEPTION, "cannot fail"); |
|
908 |
ik->itable().initialize_itable(true, THREAD); assert(!HAS_PENDING_EXCEPTION, "cannot fail"); |
|
909 |
} |
|
910 |
||
911 |
void DynamicArchiveBuilder::set_symbols_permanent() { |
|
912 |
int count = _symbols->length(); |
|
913 |
for (int i=0; i<count; i++) { |
|
914 |
Symbol* s = _symbols->at(i); |
|
915 |
s->set_permanent(); |
|
916 |
||
917 |
if (log_is_enabled(Trace, cds, dynamic)) { |
|
918 |
ResourceMark rm; |
|
919 |
log_trace(cds, dynamic)("symbols[%4i] = " PTR_FORMAT " %s", i, p2i(to_target(s)), s->as_quoted_ascii()); |
|
920 |
} |
|
921 |
} |
|
922 |
} |
|
923 |
||
924 |
class RelocateBufferToTarget: public BitMapClosure { |
|
925 |
DynamicArchiveBuilder *_builder; |
|
926 |
address* _buffer_bottom; |
|
927 |
intx _buffer_to_target_delta; |
|
928 |
public: |
|
929 |
RelocateBufferToTarget(DynamicArchiveBuilder* builder, address* bottom, intx delta) : |
|
930 |
_builder(builder), _buffer_bottom(bottom), _buffer_to_target_delta(delta) {} |
|
931 |
||
932 |
bool do_bit(size_t offset) { |
|
933 |
address* p = _buffer_bottom + offset; |
|
934 |
assert(_builder->is_in_buffer_space(p), "pointer must live in buffer space"); |
|
935 |
||
936 |
address old_ptr = *p; |
|
937 |
if (_builder->is_in_buffer_space(old_ptr)) { |
|
938 |
address new_ptr = old_ptr + _buffer_to_target_delta; |
|
939 |
log_trace(cds, dynamic)("Final patch: @%6d [" PTR_FORMAT " -> " PTR_FORMAT "] " PTR_FORMAT " => " PTR_FORMAT, |
|
940 |
(int)offset, p2i(p), p2i(_builder->to_target(p)), |
|
941 |
p2i(old_ptr), p2i(new_ptr)); |
|
942 |
*p = new_ptr; |
|
943 |
} |
|
944 |
||
945 |
return true; // keep iterating |
|
946 |
} |
|
947 |
}; |
|
948 |
||
949 |
void DynamicArchiveBuilder::relocate_buffer_to_target() { |
|
950 |
RelocateBufferToTarget patcher(this, (address*)_alloc_bottom, _buffer_to_target_delta); |
|
59070
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
951 |
ArchivePtrMarker::ptrmap()->iterate(&patcher); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
952 |
|
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
953 |
Array<u8>* table = FileMapInfo::shared_path_table().table(); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
954 |
SharedPathTable runtime_table(to_target(table), FileMapInfo::shared_path_table().size()); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
955 |
_header->set_shared_path_table(runtime_table); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
956 |
|
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
957 |
address relocatable_base = (address)SharedBaseAddress; |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
958 |
address relocatable_end = (address)(current_dump_space()->top()) + _buffer_to_target_delta; |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
959 |
|
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
960 |
intx addr_delta = MetaspaceShared::final_delta(); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
961 |
if (addr_delta == 0) { |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
962 |
ArchivePtrMarker::compact(relocatable_base, relocatable_end); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
963 |
} else { |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
964 |
// The base archive is NOT mapped at Arguments::default_SharedBaseAddress() (due to ASLR). |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
965 |
// This means that the current content of the dynamic archive is based on a random |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
966 |
// address. Let's relocate all the pointers, so that it can be mapped to |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
967 |
// Arguments::default_SharedBaseAddress() without runtime relocation. |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
968 |
// |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
969 |
// Note: both the base and dynamic archive are written with |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
970 |
// FileMapHeader::_shared_base_address == Arguments::default_SharedBaseAddress() |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
971 |
|
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
972 |
// Patch all pointers that are marked by ptrmap within this region, |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
973 |
// where we have just dumped all the metaspace data. |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
974 |
address patch_base = (address)_alloc_bottom; |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
975 |
address patch_end = (address)current_dump_space()->top(); |
54927 | 976 |
|
59070
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
977 |
// the current value of the pointers to be patched must be within this |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
978 |
// range (i.e., must point to either the top archive (as currently mapped), or to the |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
979 |
// (targeted address of) the top archive) |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
980 |
address valid_old_base = relocatable_base; |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
981 |
address valid_old_end = relocatable_end; |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
982 |
size_t base_plus_top_size = valid_old_end - valid_old_base; |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
983 |
size_t top_size = patch_end - patch_base; |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
984 |
size_t base_size = base_plus_top_size - top_size; |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
985 |
assert(base_plus_top_size > base_size, "no overflow"); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
986 |
assert(base_plus_top_size > top_size, "no overflow"); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
987 |
|
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
988 |
// after patching, the pointers must point inside this range |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
989 |
// (the requested location of the archive, as mapped at runtime). |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
990 |
address valid_new_base = (address)Arguments::default_SharedBaseAddress(); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
991 |
address valid_new_end = valid_new_base + base_plus_top_size; |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
992 |
|
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
993 |
log_debug(cds)("Relocating archive from [" INTPTR_FORMAT " - " INTPTR_FORMAT "] to " |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
994 |
"[" INTPTR_FORMAT " - " INTPTR_FORMAT "], delta = " INTX_FORMAT " bytes", |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
995 |
p2i(patch_base + base_size), p2i(patch_end), |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
996 |
p2i(valid_new_base + base_size), p2i(valid_new_end), addr_delta); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
997 |
|
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
998 |
SharedDataRelocator<true> patcher((address*)patch_base, (address*)patch_end, valid_old_base, valid_old_end, |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
999 |
valid_new_base, valid_new_end, addr_delta, ArchivePtrMarker::ptrmap()); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
1000 |
ArchivePtrMarker::ptrmap()->iterate(&patcher); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
1001 |
ArchivePtrMarker::compact(patcher.max_non_null_offset()); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
1002 |
} |
54927 | 1003 |
} |
1004 |
||
58277
00a98f0aa1b3
8231257: Avoid calling FileMapInfo::write_region twice
iklam
parents:
58096
diff
changeset
|
1005 |
void DynamicArchiveBuilder::write_regions(FileMapInfo* dynamic_info) { |
54927 | 1006 |
dynamic_info->write_region(MetaspaceShared::rw, |
1007 |
MetaspaceShared::read_write_dump_space()->base(), |
|
1008 |
MetaspaceShared::read_write_dump_space()->used(), |
|
1009 |
/*read_only=*/false,/*allow_exec=*/false); |
|
1010 |
dynamic_info->write_region(MetaspaceShared::ro, |
|
1011 |
MetaspaceShared::read_only_dump_space()->base(), |
|
1012 |
MetaspaceShared::read_only_dump_space()->used(), |
|
1013 |
/*read_only=*/true, /*allow_exec=*/false); |
|
1014 |
dynamic_info->write_region(MetaspaceShared::mc, |
|
1015 |
MetaspaceShared::misc_code_dump_space()->base(), |
|
1016 |
MetaspaceShared::misc_code_dump_space()->used(), |
|
1017 |
/*read_only=*/false,/*allow_exec=*/true); |
|
59070
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
1018 |
dynamic_info->write_bitmap_region(ArchivePtrMarker::ptrmap()); |
54927 | 1019 |
} |
1020 |
||
58278
e47b459b315c
8231278: Rename FileMapHeader::_read_only_tables_start to _serialized_data_start
iklam
parents:
58277
diff
changeset
|
1021 |
void DynamicArchiveBuilder::write_archive(char* serialized_data_start) { |
54927 | 1022 |
int num_klasses = _klasses->length(); |
1023 |
int num_symbols = _symbols->length(); |
|
1024 |
||
58278
e47b459b315c
8231278: Rename FileMapHeader::_read_only_tables_start to _serialized_data_start
iklam
parents:
58277
diff
changeset
|
1025 |
_header->set_serialized_data_start(to_target(serialized_data_start)); |
54927 | 1026 |
|
1027 |
FileMapInfo* dynamic_info = FileMapInfo::dynamic_info(); |
|
1028 |
assert(dynamic_info != NULL, "Sanity"); |
|
1029 |
||
1030 |
// Now write the archived data including the file offsets. |
|
1031 |
const char* archive_name = Arguments::GetSharedDynamicArchivePath(); |
|
1032 |
dynamic_info->open_for_write(archive_name); |
|
58277
00a98f0aa1b3
8231257: Avoid calling FileMapInfo::write_region twice
iklam
parents:
58096
diff
changeset
|
1033 |
write_regions(dynamic_info); |
59070
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
1034 |
dynamic_info->set_final_requested_base((char*)Arguments::default_SharedBaseAddress()); |
58277
00a98f0aa1b3
8231257: Avoid calling FileMapInfo::write_region twice
iklam
parents:
58096
diff
changeset
|
1035 |
dynamic_info->set_header_crc(dynamic_info->compute_header_crc()); |
00a98f0aa1b3
8231257: Avoid calling FileMapInfo::write_region twice
iklam
parents:
58096
diff
changeset
|
1036 |
dynamic_info->write_header(); |
54927 | 1037 |
dynamic_info->close(); |
1038 |
||
1039 |
address base = to_target(_alloc_bottom); |
|
1040 |
address top = address(current_dump_space()->top()) + _buffer_to_target_delta; |
|
58096 | 1041 |
size_t file_size = pointer_delta(top, base, sizeof(char)); |
54927 | 1042 |
|
59070
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
1043 |
base += MetaspaceShared::final_delta(); |
22ee476cc664
8231610: Relocate the CDS archive if it cannot be mapped to the requested address
iklam
parents:
59056
diff
changeset
|
1044 |
top += MetaspaceShared::final_delta(); |
58096 | 1045 |
log_info(cds, dynamic)("Written dynamic archive " PTR_FORMAT " - " PTR_FORMAT |
1046 |
" [" SIZE_FORMAT " bytes header, " SIZE_FORMAT " bytes total]", |
|
1047 |
p2i(base), p2i(top), _header->header_size(), file_size); |
|
54927 | 1048 |
log_info(cds, dynamic)("%d klasses; %d symbols", num_klasses, num_symbols); |
1049 |
} |
|
1050 |
||
1051 |
||
1052 |
class VM_PopulateDynamicDumpSharedSpace: public VM_Operation { |
|
1053 |
DynamicArchiveBuilder* _builder; |
|
1054 |
public: |
|
1055 |
VM_PopulateDynamicDumpSharedSpace(DynamicArchiveBuilder* builder) : _builder(builder) {} |
|
1056 |
VMOp_Type type() const { return VMOp_PopulateDumpSharedSpace; } |
|
1057 |
void doit() { |
|
1058 |
ResourceMark rm; |
|
1059 |
if (SystemDictionaryShared::empty_dumptime_table()) { |
|
1060 |
log_warning(cds, dynamic)("There is no class to be included in the dynamic archive."); |
|
1061 |
return; |
|
1062 |
} |
|
1063 |
if (AllowArchivingWithJavaAgent) { |
|
1064 |
warning("This archive was created with AllowArchivingWithJavaAgent. It should be used " |
|
1065 |
"for testing purposes only and should not be used in a production environment"); |
|
1066 |
} |
|
1067 |
FileMapInfo::check_nonempty_dir_in_shared_path_table(); |
|
1068 |
||
1069 |
_builder->doit(); |
|
1070 |
} |
|
1071 |
}; |
|
1072 |
||
1073 |
||
1074 |
void DynamicArchive::dump() { |
|
1075 |
if (Arguments::GetSharedDynamicArchivePath() == NULL) { |
|
1076 |
log_warning(cds, dynamic)("SharedDynamicArchivePath is not specified"); |
|
1077 |
return; |
|
1078 |
} |
|
1079 |
||
1080 |
DynamicArchiveBuilder builder; |
|
1081 |
_builder = &builder; |
|
1082 |
VM_PopulateDynamicDumpSharedSpace op(&builder); |
|
1083 |
VMThread::execute(&op); |
|
1084 |
_builder = NULL; |
|
1085 |
} |
|
1086 |
||
1087 |
address DynamicArchive::original_to_buffer_impl(address orig_obj) { |
|
1088 |
assert(DynamicDumpSharedSpaces, "must be"); |
|
1089 |
address buff_obj = _builder->get_new_loc(orig_obj); |
|
1090 |
assert(buff_obj != NULL, "orig_obj must be used by the dynamic archive"); |
|
1091 |
assert(buff_obj != orig_obj, "call this only when you know orig_obj must be copied and not just referenced"); |
|
1092 |
assert(_builder->is_in_buffer_space(buff_obj), "must be"); |
|
1093 |
return buff_obj; |
|
1094 |
} |
|
1095 |
||
1096 |
address DynamicArchive::buffer_to_target_impl(address buff_obj) { |
|
1097 |
assert(DynamicDumpSharedSpaces, "must be"); |
|
1098 |
assert(_builder->is_in_buffer_space(buff_obj), "must be"); |
|
1099 |
return _builder->to_target(buff_obj); |
|
1100 |
} |
|
1101 |
||
1102 |
address DynamicArchive::original_to_target_impl(address orig_obj) { |
|
1103 |
assert(DynamicDumpSharedSpaces, "must be"); |
|
1104 |
if (MetaspaceShared::is_in_shared_metaspace(orig_obj)) { |
|
1105 |
// This happens when the top archive points to a Symbol* in the base archive. |
|
1106 |
return orig_obj; |
|
1107 |
} |
|
1108 |
address buff_obj = _builder->get_new_loc(orig_obj); |
|
1109 |
assert(buff_obj != NULL, "orig_obj must be used by the dynamic archive"); |
|
1110 |
if (buff_obj == orig_obj) { |
|
1111 |
// We are storing a pointer to an original object into the dynamic buffer. E.g., |
|
1112 |
// a Symbol* that used by both the base and top archives. |
|
1113 |
assert(MetaspaceShared::is_in_shared_metaspace(orig_obj), "must be"); |
|
1114 |
return orig_obj; |
|
1115 |
} else { |
|
1116 |
return _builder->to_target(buff_obj); |
|
1117 |
} |
|
1118 |
} |
|
1119 |
||
1120 |
uintx DynamicArchive::object_delta_uintx(void* buff_obj) { |
|
1121 |
assert(DynamicDumpSharedSpaces, "must be"); |
|
1122 |
address target_obj = _builder->to_target_no_check(address(buff_obj)); |
|
1123 |
assert(uintx(target_obj) >= SharedBaseAddress, "must be"); |
|
1124 |
return uintx(target_obj) - SharedBaseAddress; |
|
1125 |
} |
|
1126 |
||
1127 |
bool DynamicArchive::is_in_target_space(void *obj) { |
|
1128 |
assert(DynamicDumpSharedSpaces, "must be"); |
|
1129 |
return _builder->is_in_target_space(obj); |
|
1130 |
} |
|
1131 |
||
1132 |
||
1133 |
DynamicArchiveBuilder* DynamicArchive::_builder = NULL; |
|
1134 |
||
1135 |
||
1136 |
bool DynamicArchive::validate(FileMapInfo* dynamic_info) { |
|
1137 |
// Check if the recorded base archive matches with the current one |
|
1138 |
FileMapInfo* base_info = FileMapInfo::current_info(); |
|
58096 | 1139 |
DynamicArchiveHeader* dynamic_header = dynamic_info->dynamic_header(); |
54927 | 1140 |
|
1141 |
// Check the header crc |
|
58096 | 1142 |
if (dynamic_header->base_header_crc() != base_info->crc()) { |
54927 | 1143 |
FileMapInfo::fail_continue("Archive header checksum verification failed."); |
1144 |
return false; |
|
1145 |
} |
|
1146 |
||
1147 |
// Check each space's crc |
|
1148 |
for (int i = 0; i < MetaspaceShared::n_regions; i++) { |
|
58096 | 1149 |
if (dynamic_header->base_region_crc(i) != base_info->space_crc(i)) { |
54927 | 1150 |
FileMapInfo::fail_continue("Archive region #%d checksum verification failed.", i); |
1151 |
return false; |
|
1152 |
} |
|
1153 |
} |
|
1154 |
||
1155 |
// Validate the dynamic archived shared path table, and set the global |
|
1156 |
// _shared_path_table to that. |
|
1157 |
if (!dynamic_info->validate_shared_path_table()) { |
|
1158 |
return false; |
|
1159 |
} |
|
1160 |
return true; |
|
1161 |
} |