changeset 52062 | 8dbf1a13af49 |
parent 52047 | 7bc8b456e5ac |
child 52319 | 625f6c742392 |
52061:070186461dbb | 52062:8dbf1a13af49 |
---|---|
22 * |
22 * |
23 */ |
23 */ |
24 |
24 |
25 #include "precompiled.hpp" |
25 #include "precompiled.hpp" |
26 #include "classfile/javaClasses.inline.hpp" |
26 #include "classfile/javaClasses.inline.hpp" |
27 #include "classfile/stringTable.hpp" |
|
27 #include "classfile/symbolTable.hpp" |
28 #include "classfile/symbolTable.hpp" |
28 #include "classfile/vmSymbols.hpp" |
29 #include "classfile/vmSymbols.hpp" |
29 #include "logging/log.hpp" |
30 #include "logging/log.hpp" |
30 #include "logging/logMessage.hpp" |
31 #include "logging/logMessage.hpp" |
31 #include "logging/logStream.hpp" |
32 #include "logging/logStream.hpp" |
33 #include "memory/filemap.hpp" |
|
32 #include "memory/heapShared.inline.hpp" |
34 #include "memory/heapShared.inline.hpp" |
33 #include "memory/iterator.inline.hpp" |
35 #include "memory/iterator.inline.hpp" |
34 #include "memory/metadataFactory.hpp" |
36 #include "memory/metadataFactory.hpp" |
35 #include "memory/metaspaceClosure.hpp" |
37 #include "memory/metaspaceClosure.hpp" |
36 #include "memory/metaspaceShared.inline.hpp" |
|
37 #include "memory/resourceArea.hpp" |
38 #include "memory/resourceArea.hpp" |
38 #include "oops/compressedOops.inline.hpp" |
39 #include "oops/compressedOops.inline.hpp" |
39 #include "oops/oop.inline.hpp" |
40 #include "oops/oop.inline.hpp" |
40 #include "runtime/fieldDescriptor.inline.hpp" |
41 #include "runtime/fieldDescriptor.inline.hpp" |
42 #include "runtime/safepointVerifiers.hpp" |
|
41 #include "utilities/bitMap.inline.hpp" |
43 #include "utilities/bitMap.inline.hpp" |
44 #if INCLUDE_G1GC |
|
45 #include "gc/g1/g1CollectedHeap.hpp" |
|
46 #endif |
|
42 |
47 |
43 #if INCLUDE_CDS_JAVA_HEAP |
48 #if INCLUDE_CDS_JAVA_HEAP |
49 |
|
50 bool HeapShared::_open_archive_heap_region_mapped = false; |
|
51 bool HeapShared::_archive_heap_region_fixed = false; |
|
52 |
|
44 address HeapShared::_narrow_oop_base; |
53 address HeapShared::_narrow_oop_base; |
45 int HeapShared::_narrow_oop_shift; |
54 int HeapShared::_narrow_oop_shift; |
55 |
|
56 //////////////////////////////////////////////////////////////// |
|
57 // |
|
58 // Java heap object archiving support |
|
59 // |
|
60 //////////////////////////////////////////////////////////////// |
|
61 void HeapShared::fixup_mapped_heap_regions() { |
|
62 FileMapInfo *mapinfo = FileMapInfo::current_info(); |
|
63 mapinfo->fixup_mapped_heap_regions(); |
|
64 set_archive_heap_region_fixed(); |
|
65 } |
|
66 |
|
67 unsigned HeapShared::oop_hash(oop const& p) { |
|
68 assert(!p->mark()->has_bias_pattern(), |
|
69 "this object should never have been locked"); // so identity_hash won't safepoin |
|
70 unsigned hash = (unsigned)p->identity_hash(); |
|
71 return hash; |
|
72 } |
|
73 |
|
74 HeapShared::ArchivedObjectCache* HeapShared::_archived_object_cache = NULL; |
|
75 oop HeapShared::find_archived_heap_object(oop obj) { |
|
76 assert(DumpSharedSpaces, "dump-time only"); |
|
77 ArchivedObjectCache* cache = archived_object_cache(); |
|
78 oop* p = cache->get(obj); |
|
79 if (p != NULL) { |
|
80 return *p; |
|
81 } else { |
|
82 return NULL; |
|
83 } |
|
84 } |
|
85 |
|
86 oop HeapShared::archive_heap_object(oop obj, Thread* THREAD) { |
|
87 assert(DumpSharedSpaces, "dump-time only"); |
|
88 |
|
89 oop ao = find_archived_heap_object(obj); |
|
90 if (ao != NULL) { |
|
91 // already archived |
|
92 return ao; |
|
93 } |
|
94 |
|
95 int len = obj->size(); |
|
96 if (G1CollectedHeap::heap()->is_archive_alloc_too_large(len)) { |
|
97 log_debug(cds, heap)("Cannot archive, object (" PTR_FORMAT ") is too large: " SIZE_FORMAT, |
|
98 p2i(obj), (size_t)obj->size()); |
|
99 return NULL; |
|
100 } |
|
101 |
|
102 // Pre-compute object identity hash at CDS dump time. |
|
103 obj->identity_hash(); |
|
104 |
|
105 oop archived_oop = (oop)G1CollectedHeap::heap()->archive_mem_allocate(len); |
|
106 if (archived_oop != NULL) { |
|
107 Copy::aligned_disjoint_words((HeapWord*)obj, (HeapWord*)archived_oop, len); |
|
108 MetaspaceShared::relocate_klass_ptr(archived_oop); |
|
109 ArchivedObjectCache* cache = archived_object_cache(); |
|
110 cache->put(obj, archived_oop); |
|
111 log_debug(cds, heap)("Archived heap object " PTR_FORMAT " ==> " PTR_FORMAT, |
|
112 p2i(obj), p2i(archived_oop)); |
|
113 } else { |
|
114 log_error(cds, heap)( |
|
115 "Cannot allocate space for object " PTR_FORMAT " in archived heap region", |
|
116 p2i(obj)); |
|
117 vm_exit(1); |
|
118 } |
|
119 return archived_oop; |
|
120 } |
|
121 |
|
122 oop HeapShared::materialize_archived_object(narrowOop v) { |
|
123 assert(archive_heap_region_fixed(), |
|
124 "must be called after archive heap regions are fixed"); |
|
125 if (!CompressedOops::is_null(v)) { |
|
126 oop obj = HeapShared::decode_from_archive(v); |
|
127 return G1CollectedHeap::heap()->materialize_archived_object(obj); |
|
128 } |
|
129 return NULL; |
|
130 } |
|
131 |
|
132 void HeapShared::archive_klass_objects(Thread* THREAD) { |
|
133 GrowableArray<Klass*>* klasses = MetaspaceShared::collected_klasses(); |
|
134 assert(klasses != NULL, "sanity"); |
|
135 for (int i = 0; i < klasses->length(); i++) { |
|
136 Klass* k = klasses->at(i); |
|
137 |
|
138 // archive mirror object |
|
139 java_lang_Class::archive_mirror(k, CHECK); |
|
140 |
|
141 // archive the resolved_referenes array |
|
142 if (k->is_instance_klass()) { |
|
143 InstanceKlass* ik = InstanceKlass::cast(k); |
|
144 ik->constants()->archive_resolved_references(THREAD); |
|
145 } |
|
146 } |
|
147 } |
|
148 |
|
149 void HeapShared::archive_java_heap_objects(GrowableArray<MemRegion> *closed, |
|
150 GrowableArray<MemRegion> *open) { |
|
151 if (!is_heap_object_archiving_allowed()) { |
|
152 if (log_is_enabled(Info, cds)) { |
|
153 log_info(cds)( |
|
154 "Archived java heap is not supported as UseG1GC, " |
|
155 "UseCompressedOops and UseCompressedClassPointers are required." |
|
156 "Current settings: UseG1GC=%s, UseCompressedOops=%s, UseCompressedClassPointers=%s.", |
|
157 BOOL_TO_STR(UseG1GC), BOOL_TO_STR(UseCompressedOops), |
|
158 BOOL_TO_STR(UseCompressedClassPointers)); |
|
159 } |
|
160 return; |
|
161 } |
|
162 |
|
163 { |
|
164 NoSafepointVerifier nsv; |
|
165 |
|
166 // Cache for recording where the archived objects are copied to |
|
167 create_archived_object_cache(); |
|
168 |
|
169 tty->print_cr("Dumping objects to closed archive heap region ..."); |
|
170 NOT_PRODUCT(StringTable::verify()); |
|
171 copy_closed_archive_heap_objects(closed); |
|
172 |
|
173 tty->print_cr("Dumping objects to open archive heap region ..."); |
|
174 copy_open_archive_heap_objects(open); |
|
175 |
|
176 destroy_archived_object_cache(); |
|
177 } |
|
178 |
|
179 G1HeapVerifier::verify_archive_regions(); |
|
180 } |
|
181 |
|
182 void HeapShared::copy_closed_archive_heap_objects( |
|
183 GrowableArray<MemRegion> * closed_archive) { |
|
184 assert(is_heap_object_archiving_allowed(), "Cannot archive java heap objects"); |
|
185 |
|
186 Thread* THREAD = Thread::current(); |
|
187 G1CollectedHeap::heap()->begin_archive_alloc_range(); |
|
188 |
|
189 // Archive interned string objects |
|
190 StringTable::write_to_archive(); |
|
191 |
|
192 G1CollectedHeap::heap()->end_archive_alloc_range(closed_archive, |
|
193 os::vm_allocation_granularity()); |
|
194 } |
|
195 |
|
196 void HeapShared::copy_open_archive_heap_objects( |
|
197 GrowableArray<MemRegion> * open_archive) { |
|
198 assert(is_heap_object_archiving_allowed(), "Cannot archive java heap objects"); |
|
199 |
|
200 Thread* THREAD = Thread::current(); |
|
201 G1CollectedHeap::heap()->begin_archive_alloc_range(true /* open */); |
|
202 |
|
203 java_lang_Class::archive_basic_type_mirrors(THREAD); |
|
204 |
|
205 archive_klass_objects(THREAD); |
|
206 |
|
207 archive_object_subgraphs(THREAD); |
|
208 |
|
209 G1CollectedHeap::heap()->end_archive_alloc_range(open_archive, |
|
210 os::vm_allocation_granularity()); |
|
211 } |
|
212 |
|
213 void HeapShared::init_narrow_oop_decoding(address base, int shift) { |
|
214 _narrow_oop_base = base; |
|
215 _narrow_oop_shift = shift; |
|
216 } |
|
217 |
|
218 // |
|
219 // Subgraph archiving support |
|
220 // |
|
46 HeapShared::DumpTimeKlassSubGraphInfoTable* HeapShared::_dump_time_subgraph_info_table = NULL; |
221 HeapShared::DumpTimeKlassSubGraphInfoTable* HeapShared::_dump_time_subgraph_info_table = NULL; |
47 HeapShared::RunTimeKlassSubGraphInfoTable HeapShared::_run_time_subgraph_info_table; |
222 HeapShared::RunTimeKlassSubGraphInfoTable HeapShared::_run_time_subgraph_info_table; |
48 |
223 |
49 // Get the subgraph_info for Klass k. A new subgraph_info is created if |
224 // Get the subgraph_info for Klass k. A new subgraph_info is created if |
50 // there is no existing one for k. The subgraph_info records the relocated |
225 // there is no existing one for k. The subgraph_info records the relocated |
212 void HeapShared::serialize_subgraph_info_table_header(SerializeClosure* soc) { |
387 void HeapShared::serialize_subgraph_info_table_header(SerializeClosure* soc) { |
213 _run_time_subgraph_info_table.serialize_header(soc); |
388 _run_time_subgraph_info_table.serialize_header(soc); |
214 } |
389 } |
215 |
390 |
216 void HeapShared::initialize_from_archived_subgraph(Klass* k) { |
391 void HeapShared::initialize_from_archived_subgraph(Klass* k) { |
217 if (!MetaspaceShared::open_archive_heap_region_mapped()) { |
392 if (!open_archive_heap_region_mapped()) { |
218 return; // nothing to do |
393 return; // nothing to do |
219 } |
394 } |
220 assert(!DumpSharedSpaces, "Should not be called with DumpSharedSpaces"); |
395 assert(!DumpSharedSpaces, "Should not be called with DumpSharedSpaces"); |
221 |
396 |
222 unsigned int hash = primitive_hash<Klass*>(k); |
397 unsigned int hash = primitive_hash<Klass*>(k); |
272 for (i = 0; i < efr_len;) { |
447 for (i = 0; i < efr_len;) { |
273 int field_offset = entry_field_records->at(i); |
448 int field_offset = entry_field_records->at(i); |
274 // The object refereced by the field becomes 'known' by GC from this |
449 // The object refereced by the field becomes 'known' by GC from this |
275 // point. All objects in the subgraph reachable from the object are |
450 // point. All objects in the subgraph reachable from the object are |
276 // also 'known' by GC. |
451 // also 'known' by GC. |
277 oop v = MetaspaceShared::materialize_archived_object( |
452 oop v = materialize_archived_object(entry_field_records->at(i+1)); |
278 entry_field_records->at(i+1)); |
|
279 m->obj_field_put(field_offset, v); |
453 m->obj_field_put(field_offset, v); |
280 i += 2; |
454 i += 2; |
281 |
455 |
282 log_debug(cds, heap)(" " PTR_FORMAT " init field @ %2d = " PTR_FORMAT, p2i(k), field_offset, p2i(v)); |
456 log_debug(cds, heap)(" " PTR_FORMAT " init field @ %2d = " PTR_FORMAT, p2i(k), field_offset, p2i(v)); |
283 } |
457 } |
308 |
482 |
309 protected: |
483 protected: |
310 template <class T> void do_oop_work(T *p) { |
484 template <class T> void do_oop_work(T *p) { |
311 oop obj = RawAccess<>::oop_load(p); |
485 oop obj = RawAccess<>::oop_load(p); |
312 if (!CompressedOops::is_null(obj)) { |
486 if (!CompressedOops::is_null(obj)) { |
313 assert(!MetaspaceShared::is_archive_object(obj), |
487 assert(!HeapShared::is_archived_object(obj), |
314 "original objects must not point to archived objects"); |
488 "original objects must not point to archived objects"); |
315 |
489 |
316 size_t field_delta = pointer_delta(p, _orig_referencing_obj, sizeof(char)); |
490 size_t field_delta = pointer_delta(p, _orig_referencing_obj, sizeof(char)); |
317 T* new_p = (T*)(address(_archived_referencing_obj) + field_delta); |
491 T* new_p = (T*)(address(_archived_referencing_obj) + field_delta); |
318 Thread* THREAD = _thread; |
492 Thread* THREAD = _thread; |
327 obj->print_on(&out); |
501 obj->print_on(&out); |
328 } |
502 } |
329 |
503 |
330 oop archived = HeapShared::archive_reachable_objects_from(_level + 1, _subgraph_info, obj, THREAD); |
504 oop archived = HeapShared::archive_reachable_objects_from(_level + 1, _subgraph_info, obj, THREAD); |
331 assert(archived != NULL, "VM should have exited with unarchivable objects for _level > 1"); |
505 assert(archived != NULL, "VM should have exited with unarchivable objects for _level > 1"); |
332 assert(MetaspaceShared::is_archive_object(archived), "must be"); |
506 assert(HeapShared::is_archived_object(archived), "must be"); |
333 |
507 |
334 if (!_record_klasses_only) { |
508 if (!_record_klasses_only) { |
335 // Update the reference in the archived copy of the referencing object. |
509 // Update the reference in the archived copy of the referencing object. |
336 log_debug(cds, heap)("(%d) updating oop @[" PTR_FORMAT "] " PTR_FORMAT " ==> " PTR_FORMAT, |
510 log_debug(cds, heap)("(%d) updating oop @[" PTR_FORMAT "] " PTR_FORMAT " ==> " PTR_FORMAT, |
337 _level, p2i(new_p), p2i(obj), p2i(archived)); |
511 _level, p2i(new_p), p2i(obj), p2i(archived)); |
345 // (2) If orig_obj has not been seen yet (since start_recording_subgraph() was called), |
519 // (2) If orig_obj has not been seen yet (since start_recording_subgraph() was called), |
346 // trace all objects that are reachable from it, and make sure these objects are archived. |
520 // trace all objects that are reachable from it, and make sure these objects are archived. |
347 // (3) Record the klasses of all orig_obj and all reachable objects. |
521 // (3) Record the klasses of all orig_obj and all reachable objects. |
348 oop HeapShared::archive_reachable_objects_from(int level, KlassSubGraphInfo* subgraph_info, oop orig_obj, TRAPS) { |
522 oop HeapShared::archive_reachable_objects_from(int level, KlassSubGraphInfo* subgraph_info, oop orig_obj, TRAPS) { |
349 assert(orig_obj != NULL, "must be"); |
523 assert(orig_obj != NULL, "must be"); |
350 assert(!MetaspaceShared::is_archive_object(orig_obj), "sanity"); |
524 assert(!is_archived_object(orig_obj), "sanity"); |
351 |
525 |
352 // java.lang.Class instances cannot be included in an archived |
526 // java.lang.Class instances cannot be included in an archived |
353 // object sub-graph. |
527 // object sub-graph. |
354 if (java_lang_Class::is_instance(orig_obj)) { |
528 if (java_lang_Class::is_instance(orig_obj)) { |
355 log_error(cds, heap)("(%d) Unknown java.lang.Class object is in the archived sub-graph", level); |
529 log_error(cds, heap)("(%d) Unknown java.lang.Class object is in the archived sub-graph", level); |
356 vm_exit(1); |
530 vm_exit(1); |
357 } |
531 } |
358 |
532 |
359 oop archived_obj = MetaspaceShared::find_archived_heap_object(orig_obj); |
533 oop archived_obj = find_archived_heap_object(orig_obj); |
360 if (java_lang_String::is_instance(orig_obj) && archived_obj != NULL) { |
534 if (java_lang_String::is_instance(orig_obj) && archived_obj != NULL) { |
361 // To save time, don't walk strings that are already archived. They just contain |
535 // To save time, don't walk strings that are already archived. They just contain |
362 // pointers to a type array, whose klass doesn't need to be recorded. |
536 // pointers to a type array, whose klass doesn't need to be recorded. |
363 return archived_obj; |
537 return archived_obj; |
364 } |
538 } |
371 } |
545 } |
372 |
546 |
373 bool record_klasses_only = (archived_obj != NULL); |
547 bool record_klasses_only = (archived_obj != NULL); |
374 if (archived_obj == NULL) { |
548 if (archived_obj == NULL) { |
375 ++_num_new_archived_objs; |
549 ++_num_new_archived_objs; |
376 archived_obj = MetaspaceShared::archive_heap_object(orig_obj, THREAD); |
550 archived_obj = archive_heap_object(orig_obj, THREAD); |
377 if (archived_obj == NULL) { |
551 if (archived_obj == NULL) { |
378 // Skip archiving the sub-graph referenced from the current entry field. |
552 // Skip archiving the sub-graph referenced from the current entry field. |
379 ResourceMark rm; |
553 ResourceMark rm; |
380 log_error(cds, heap)( |
554 log_error(cds, heap)( |
381 "Cannot archive the sub-graph referenced from %s object (" |
555 "Cannot archive the sub-graph referenced from %s object (" |
445 TRAPS) { |
619 TRAPS) { |
446 assert(DumpSharedSpaces, "dump time only"); |
620 assert(DumpSharedSpaces, "dump time only"); |
447 assert(k->is_shared_boot_class(), "must be boot class"); |
621 assert(k->is_shared_boot_class(), "must be boot class"); |
448 |
622 |
449 oop m = k->java_mirror(); |
623 oop m = k->java_mirror(); |
450 oop archived_m = MetaspaceShared::find_archived_heap_object(m); |
624 oop archived_m = find_archived_heap_object(m); |
451 if (CompressedOops::is_null(archived_m)) { |
625 if (CompressedOops::is_null(archived_m)) { |
452 return; |
626 return; |
453 } |
627 } |
454 |
628 |
455 KlassSubGraphInfo* subgraph_info = get_subgraph_info(k); |
629 KlassSubGraphInfo* subgraph_info = get_subgraph_info(k); |
506 void HeapShared::verify_subgraph_from_static_field(InstanceKlass* k, int field_offset) { |
680 void HeapShared::verify_subgraph_from_static_field(InstanceKlass* k, int field_offset) { |
507 assert(DumpSharedSpaces, "dump time only"); |
681 assert(DumpSharedSpaces, "dump time only"); |
508 assert(k->is_shared_boot_class(), "must be boot class"); |
682 assert(k->is_shared_boot_class(), "must be boot class"); |
509 |
683 |
510 oop m = k->java_mirror(); |
684 oop m = k->java_mirror(); |
511 oop archived_m = MetaspaceShared::find_archived_heap_object(m); |
685 oop archived_m = find_archived_heap_object(m); |
512 if (CompressedOops::is_null(archived_m)) { |
686 if (CompressedOops::is_null(archived_m)) { |
513 return; |
687 return; |
514 } |
688 } |
515 oop f = m->obj_field(field_offset); |
689 oop f = m->obj_field(field_offset); |
516 if (!CompressedOops::is_null(f)) { |
690 if (!CompressedOops::is_null(f)) { |
517 verify_subgraph_from(f); |
691 verify_subgraph_from(f); |
518 } |
692 } |
519 } |
693 } |
520 |
694 |
521 void HeapShared::verify_subgraph_from(oop orig_obj) { |
695 void HeapShared::verify_subgraph_from(oop orig_obj) { |
522 oop archived_obj = MetaspaceShared::find_archived_heap_object(orig_obj); |
696 oop archived_obj = find_archived_heap_object(orig_obj); |
523 if (archived_obj == NULL) { |
697 if (archived_obj == NULL) { |
524 // It's OK for the root of a subgraph to be not archived. See comments in |
698 // It's OK for the root of a subgraph to be not archived. See comments in |
525 // archive_reachable_objects_from(). |
699 // archive_reachable_objects_from(). |
526 return; |
700 return; |
527 } |
701 } |
544 _num_total_verifications ++; |
718 _num_total_verifications ++; |
545 if (!has_been_seen_during_subgraph_recording(obj)) { |
719 if (!has_been_seen_during_subgraph_recording(obj)) { |
546 set_has_been_seen_during_subgraph_recording(obj); |
720 set_has_been_seen_during_subgraph_recording(obj); |
547 |
721 |
548 if (is_archived) { |
722 if (is_archived) { |
549 assert(MetaspaceShared::is_archive_object(obj), "must be"); |
723 assert(is_archived_object(obj), "must be"); |
550 assert(MetaspaceShared::find_archived_heap_object(obj) == NULL, "must be"); |
724 assert(find_archived_heap_object(obj) == NULL, "must be"); |
551 } else { |
725 } else { |
552 assert(!MetaspaceShared::is_archive_object(obj), "must be"); |
726 assert(!is_archived_object(obj), "must be"); |
553 assert(MetaspaceShared::find_archived_heap_object(obj) != NULL, "must be"); |
727 assert(find_archived_heap_object(obj) != NULL, "must be"); |
554 } |
728 } |
555 |
729 |
556 VerifySharedOopClosure walker(is_archived); |
730 VerifySharedOopClosure walker(is_archived); |
557 obj->oop_iterate(&walker); |
731 obj->oop_iterate(&walker); |
558 } |
732 } |
668 info->klass = ik; |
842 info->klass = ik; |
669 info->offset = finder.offset(); |
843 info->offset = finder.offset(); |
670 } |
844 } |
671 } |
845 } |
672 |
846 |
673 void HeapShared::archive_static_fields(Thread* THREAD) { |
847 void HeapShared::archive_object_subgraphs(Thread* THREAD) { |
674 // For each class X that has one or more archived fields: |
848 // For each class X that has one or more archived fields: |
675 // [1] Dump the subgraph of each archived field |
849 // [1] Dump the subgraph of each archived field |
676 // [2] Create a list of all the class of the objects that can be reached |
850 // [2] Create a list of all the class of the objects that can be reached |
677 // by any of these static fields. |
851 // by any of these static fields. |
678 // At runtime, these classes are initialized before X's archived fields |
852 // At runtime, these classes are initialized before X's archived fields |
765 log_info(cds, heap)("calculate_oopmap: objects = %6d, embedded oops = %7d, nulls = %7d", |
939 log_info(cds, heap)("calculate_oopmap: objects = %6d, embedded oops = %7d, nulls = %7d", |
766 num_objs, finder.num_total_oops(), finder.num_null_oops()); |
940 num_objs, finder.num_total_oops(), finder.num_null_oops()); |
767 return oopmap; |
941 return oopmap; |
768 } |
942 } |
769 |
943 |
770 void HeapShared::init_narrow_oop_decoding(address base, int shift) { |
|
771 _narrow_oop_base = base; |
|
772 _narrow_oop_shift = shift; |
|
773 } |
|
774 |
|
775 // Patch all the embedded oop pointers inside an archived heap region, |
944 // Patch all the embedded oop pointers inside an archived heap region, |
776 // to be consistent with the runtime oop encoding. |
945 // to be consistent with the runtime oop encoding. |
777 class PatchEmbeddedPointers: public BitMapClosure { |
946 class PatchEmbeddedPointers: public BitMapClosure { |
778 narrowOop* _start; |
947 narrowOop* _start; |
779 |
948 |