< prev index next >
src/hotspot/share/memory/heapShared.cpp
Print this page
*** 183,194 ****
for (int i = 0; i < num_subgraphs_klasses; i++) {
Klass* subgraph_k = subgraph_klasses->at(i);
if (log_is_enabled(Info, cds, heap)) {
ResourceMark rm;
log_info(cds, heap)(
! "Archived object klass (%d): %s in %s sub-graphs",
! i, subgraph_k->external_name(), _k->external_name());
}
_subgraph_klasses->at_put(i, subgraph_k);
}
}
}
--- 183,194 ----
for (int i = 0; i < num_subgraphs_klasses; i++) {
Klass* subgraph_k = subgraph_klasses->at(i);
if (log_is_enabled(Info, cds, heap)) {
ResourceMark rm;
log_info(cds, heap)(
! "Archived object klass %s (%2d) => %s",
! _k->external_name(), i, subgraph_k->external_name());
}
_subgraph_klasses->at_put(i, subgraph_k);
}
}
}
*** 346,439 ****
class WalkOopAndArchiveClosure: public BasicOopIterateClosure {
int _level;
oop _orig_referencing_obj;
oop _archived_referencing_obj;
public:
WalkOopAndArchiveClosure(int level,
! oop orig, oop archived) : _level(level),
_orig_referencing_obj(orig),
! _archived_referencing_obj(archived) {}
void do_oop(narrowOop *p) { WalkOopAndArchiveClosure::do_oop_work(p); }
void do_oop( oop *p) { WalkOopAndArchiveClosure::do_oop_work(p); }
protected:
template <class T> void do_oop_work(T *p) {
oop obj = RawAccess<>::oop_load(p);
if (!CompressedOops::is_null(obj)) {
// A java.lang.Class instance cannot be included in an archived
// object sub-graph.
if (java_lang_Class::is_instance(obj)) {
! log_error(cds, heap)("Unknown java.lang.Class object is in the archived sub-graph");
vm_exit(1);
}
if (log_is_enabled(Debug, cds, heap)) {
- LogTarget(Debug, cds, heap) log;
- LogStream ls(log);
- outputStream* out = &ls;
ResourceMark rm;
! log.print("(%d) %s <--- referenced from: %s",
! _level, obj->klass()->external_name(),
! CompressedOops::is_null(_orig_referencing_obj) ?
! "" : _orig_referencing_obj->klass()->external_name());
! obj->print_on(out);
}
- assert(!MetaspaceShared::is_archive_object(obj),
- "original objects must not directly point to archived object");
-
- size_t field_delta = pointer_delta(
- p, _orig_referencing_obj, sizeof(char));
- T* new_p = (T*)(address(_archived_referencing_obj) + field_delta);
oop archived = MetaspaceShared::find_archived_heap_object(obj);
! if (archived != NULL) {
! // There is an archived copy existing, update reference to point
! // to the archived copy
RawAccess<IS_NOT_NULL>::oop_store(new_p, archived);
- log_debug(cds, heap)("--- found existing archived copy, store archived " PTR_FORMAT " in " PTR_FORMAT,
- p2i(archived), p2i(new_p));
- return;
}
! Thread* THREAD = Thread::current();
! // Archive the current oop before iterating through its references
! archived = MetaspaceShared::archive_heap_object(obj, THREAD);
! if (archived == NULL) {
ResourceMark rm;
! LogTarget(Error, cds, heap) log_err;
! LogStream ls_err(log_err);
! outputStream* out_err = &ls_err;
! log_err.print("Failed to archive %s object ("
! PTR_FORMAT "), size[" SIZE_FORMAT "] in sub-graph",
! obj->klass()->external_name(), p2i(obj), (size_t)obj->size());
! obj->print_on(out_err);
vm_exit(1);
}
- assert(MetaspaceShared::is_archive_object(archived), "must be archived");
- log_debug(cds, heap)("=== archiving oop " PTR_FORMAT " ==> " PTR_FORMAT,
- p2i(obj), p2i(archived));
-
- // Following the references in the current oop and archive any
- // encountered objects during the process
- WalkOopAndArchiveClosure walker(_level + 1, obj, archived);
- obj->oop_iterate(&walker);
-
- // Update the reference in the archived copy of the referencing object
- RawAccess<IS_NOT_NULL>::oop_store(new_p, archived);
- log_debug(cds,heap)("=== store archived " PTR_FORMAT " in " PTR_FORMAT,
- p2i(archived), p2i(new_p));
}
! }
! };
//
// Start from the given static field in a java mirror and archive the
// complete sub-graph of java heap objects that are reached directly
// or indirectly from the starting object by following references.
! // Currently, only ArchivedModuleGraph class instance (mirror) has archived
! // object subgraphs. Sub-graph archiving restrictions (current):
//
// - All classes of objects in the archived sub-graph (including the
// entry class) must be boot class only.
// - No java.lang.Class instance (java mirror) can be included inside
// an archived sub-graph. Mirror can only be the sub-graph entry object.
--- 346,442 ----
class WalkOopAndArchiveClosure: public BasicOopIterateClosure {
int _level;
oop _orig_referencing_obj;
oop _archived_referencing_obj;
+ Thread* _thread;
public:
WalkOopAndArchiveClosure(int level,
! oop orig, oop archived, TRAPS) : _level(level),
_orig_referencing_obj(orig),
! _archived_referencing_obj(archived),
! _thread(THREAD) {}
void do_oop(narrowOop *p) { WalkOopAndArchiveClosure::do_oop_work(p); }
void do_oop( oop *p) { WalkOopAndArchiveClosure::do_oop_work(p); }
protected:
template <class T> void do_oop_work(T *p) {
oop obj = RawAccess<>::oop_load(p);
if (!CompressedOops::is_null(obj)) {
+ assert(!MetaspaceShared::is_archive_object(obj),
+ "original objects must not directly point to archived object");
+ size_t field_delta = pointer_delta(p, _orig_referencing_obj, sizeof(char));
+ T* new_p = (T*)(address(_archived_referencing_obj) + field_delta);
+
// A java.lang.Class instance cannot be included in an archived
// object sub-graph.
if (java_lang_Class::is_instance(obj)) {
! log_error(cds, heap)("(%d) Unknown java.lang.Class object is in the archived sub-graph", _level);
vm_exit(1);
}
if (log_is_enabled(Debug, cds, heap)) {
ResourceMark rm;
! log_debug(cds, heap)("(%d) %s[" SIZE_FORMAT "] ==> " PTR_FORMAT " size %d %s", _level,
! _orig_referencing_obj->klass()->external_name(), field_delta,
! p2i(obj), obj->size() * HeapWordSize, obj->klass()->external_name());
! LogTarget(Trace, cds, heap) log;
! LogStream out(log);
! obj->print_on(&out);
}
oop archived = MetaspaceShared::find_archived_heap_object(obj);
! if (archived == NULL) {
! Thread* THREAD = _thread;
! archived = HeapShared::archive_reachable_objects_from(_level + 1, obj, THREAD);
! assert(archived != NULL, "VM should have exited");
! }
! assert(MetaspaceShared::is_archive_object(archived), "must be");
!
! // Update the reference in the archived copy of the referencing object.
! log_debug(cds, heap)("(%d) archiving oop @[" PTR_FORMAT "] " PTR_FORMAT " ==> " PTR_FORMAT,
! _level, p2i(new_p), p2i(obj), p2i(archived));
RawAccess<IS_NOT_NULL>::oop_store(new_p, archived);
}
+ }
+ };
! oop HeapShared::archive_reachable_objects_from(int level, oop orig_obj, TRAPS) {
! assert(orig_obj != NULL, "must be");
! assert(!MetaspaceShared::is_archive_object(orig_obj), "sanity");
!
! // get the archived copy of the field referenced object
! oop archived_obj = MetaspaceShared::archive_heap_object(orig_obj, THREAD);
! if (archived_obj == NULL) {
! // Skip archiving the sub-graph referenced from the current entry field.
ResourceMark rm;
! log_error(cds, heap)(
! "Cannot archive the sub-graph referenced from %s object ("
! PTR_FORMAT ") size %d, skipped.",
! orig_obj->klass()->external_name(), p2i(orig_obj), orig_obj->size() * HeapWordSize);
! if (level == 1) {
! // See runtime/appcds/cacheObject/ArchivedIntegerCacheTest.java
! return NULL;
! } else {
! // We don't know how to handle an object that has been archived, but some of its reachable
! // objects cannot be archived. Bail out for now. We might need to fix this in the future if
! // we have a real use case.
vm_exit(1);
}
}
!
! WalkOopAndArchiveClosure walker(level, orig_obj, archived_obj, THREAD);
! orig_obj->oop_iterate(&walker);
! assert(archived_obj != NULL, "must be");
! return archived_obj;
! }
//
// Start from the given static field in a java mirror and archive the
// complete sub-graph of java heap objects that are reached directly
// or indirectly from the starting object by following references.
! // Sub-graph archiving restrictions (current):
//
// - All classes of objects in the archived sub-graph (including the
// entry class) must be boot class only.
// - No java.lang.Class instance (java mirror) can be included inside
// an archived sub-graph. Mirror can only be the sub-graph entry object.
*** 468,521 ****
oop archived_m = MetaspaceShared::find_archived_heap_object(m);
if (CompressedOops::is_null(archived_m)) {
return;
}
- // obtain k's subGraph Info
KlassSubGraphInfo* subgraph_info = get_subgraph_info(k);
-
- // get the object referenced by the field
oop f = m->obj_field(field_offset);
! if (log_is_enabled(Debug, cds, heap)) {
! LogTarget(Debug, cds, heap) log;
! LogStream ls(log);
! outputStream* out = &ls;
! log.print("Start archiving from: %s::%s ", klass_name, field_name);
! if (!CompressedOops::is_null(f)) {
! f->print_on(out);
! } else {
! log.print("null");
! }
}
if (!CompressedOops::is_null(f)) {
! // get the archived copy of the field referenced object
! oop af = MetaspaceShared::archive_heap_object(f, THREAD);
if (af == NULL) {
! // Skip archiving the sub-graph referenced from the current entry field.
! ResourceMark rm;
! log_info(cds, heap)(
! "Cannot archive the sub-graph referenced from %s object ("
! PTR_FORMAT ") size[" SIZE_FORMAT "], skipped.",
! f->klass()->external_name(), p2i(f), (size_t)f->size());
! return;
! }
! if (!MetaspaceShared::is_archive_object(f)) {
! WalkOopAndArchiveClosure walker(1, f, af);
! f->oop_iterate(&walker);
! }
!
! // The field value is not preserved in the archived mirror.
// Record the field as a new subGraph entry point. The recorded
// information is restored from the archive at runtime.
subgraph_info->add_subgraph_entry_field(field_offset, af);
! if (log_is_enabled(Info, cds, heap)) {
! ResourceMark rm;
! log_info(cds, heap)(
! "Archived the sub-graph referenced from %s object " PTR_FORMAT,
! f->klass()->external_name(), p2i(f));
}
} else {
// The field contains null, we still need to record the entry point,
// so it can be restored at runtime.
subgraph_info->add_subgraph_entry_field(field_offset, NULL);
--- 471,501 ----
oop archived_m = MetaspaceShared::find_archived_heap_object(m);
if (CompressedOops::is_null(archived_m)) {
return;
}
KlassSubGraphInfo* subgraph_info = get_subgraph_info(k);
oop f = m->obj_field(field_offset);
! log_debug(cds, heap)("Start archiving from: %s::%s ", klass_name, field_name);
! if (log_is_enabled(Trace, cds, heap) && !CompressedOops::is_null(f)) {
! LogTarget(Trace, cds, heap) log;
! LogStream out(log);
! f->print_on(&out);
}
if (!CompressedOops::is_null(f)) {
! oop af = archive_reachable_objects_from(1, f, CHECK);
if (af == NULL) {
! log_error(cds, heap)("Archiving failed %s::%s (some reachable objects cannot be archived)",
! klass_name, field_name);
! } else {
! // Note: the field value is not preserved in the archived mirror.
// Record the field as a new subGraph entry point. The recorded
// information is restored from the archive at runtime.
subgraph_info->add_subgraph_entry_field(field_offset, af);
! log_info(cds, heap)("Archived field %s::%s => " PTR_FORMAT, klass_name, field_name, p2i(af));
}
} else {
// The field contains null, we still need to record the entry point,
// so it can be restored at runtime.
subgraph_info->add_subgraph_entry_field(field_offset, NULL);
*** 549,564 ****
int field_offset,
const char* field_name) {
assert(DumpSharedSpaces, "dump time only");
assert(k->is_shared_boot_class(), "must be boot class");
! if (log_is_enabled(Debug, cds, heap)) {
! LogTarget(Debug, cds, heap) log;
! LogStream ls(log);
! outputStream* out = &ls;
! log.print("Start recording from: %s::%s", klass_name, field_name);
! }
oop m = k->java_mirror();
oop f = m->obj_field(field_offset);
record_subgraph_klasses_for(get_subgraph_info(k), f);
}
--- 529,539 ----
int field_offset,
const char* field_name) {
assert(DumpSharedSpaces, "dump time only");
assert(k->is_shared_boot_class(), "must be boot class");
! log_debug(cds, heap)("Start recording from: %s::%s", klass_name, field_name);
oop m = k->java_mirror();
oop f = m->obj_field(field_offset);
record_subgraph_klasses_for(get_subgraph_info(k), f);
}
< prev index next >