335 int _level;
336 KlassSubGraphInfo* _subgraph_info;
337 oop _orig_referencing_obj;
338 oop _archived_referencing_obj;
339 public:
340 WalkOopAndArchiveClosure(int level, KlassSubGraphInfo* subgraph_info,
341 oop orig, oop archived) : _level(level),
342 _subgraph_info(subgraph_info),
343 _orig_referencing_obj(orig),
344 _archived_referencing_obj(archived) {}
345 void do_oop(narrowOop *p) { WalkOopAndArchiveClosure::do_oop_work(p); }
346 void do_oop( oop *p) { WalkOopAndArchiveClosure::do_oop_work(p); }
347
348 protected:
349 template <class T> void do_oop_work(T *p) {
350 oop obj = RawAccess<>::oop_load(p);
351 if (!CompressedOops::is_null(obj)) {
352 // A java.lang.Class instance can not be included in an archived
353 // object sub-graph.
354 if (java_lang_Class::is_instance(obj)) {
355 tty->print("Unknown java.lang.Class object is in the archived sub-graph\n");
356 vm_exit(1);
357 }
358
359 LogTarget(Debug, cds, heap) log;
360 LogStream ls(log);
361 outputStream* out = &ls;
362 {
363 ResourceMark rm;
364 log.print("(%d) %s <--- referenced from: %s",
365 _level, obj->klass()->external_name(),
366 CompressedOops::is_null(_orig_referencing_obj) ?
367 "" : _orig_referencing_obj->klass()->external_name());
368 obj->print_on(out);
369 }
370
371 if (MetaspaceShared::is_archive_object(obj)) {
372 // The current oop is an archived oop, nothing needs to be done
373 log.print("--- object is already archived ---");
374 return;
375 }
376
377 size_t field_delta = pointer_delta(
378 p, _orig_referencing_obj, sizeof(char));
379 T* new_p = (T*)(address(_archived_referencing_obj) + field_delta);
380 oop archived = MetaspaceShared::find_archived_heap_object(obj);
381 if (archived != NULL) {
382 // There is an archived copy existing, update reference to point
383 // to the archived copy
384 RawAccess<IS_NOT_NULL>::oop_store(new_p, archived);
385 log.print(
386 "--- found existing archived copy, store archived " PTR_FORMAT " in " PTR_FORMAT,
387 p2i(archived), p2i(new_p));
388 return;
389 }
390
391 int l = _level + 1;
392 Thread* THREAD = Thread::current();
393 // Archive the current oop before iterating through its references
394 archived = MetaspaceShared::archive_heap_object(obj, THREAD);
395 assert(MetaspaceShared::is_archive_object(archived), "must be archived");
396 log.print("=== archiving oop " PTR_FORMAT " ==> " PTR_FORMAT,
397 p2i(obj), p2i(archived));
398
399 // Following the references in the current oop and archive any
400 // encountered objects during the process
401 WalkOopAndArchiveClosure walker(l, _subgraph_info, obj, archived);
402 obj->oop_iterate(&walker);
403
404 // Update the reference in the archived copy of the referencing object
405 RawAccess<IS_NOT_NULL>::oop_store(new_p, archived);
406 log.print("=== store archived " PTR_FORMAT " in " PTR_FORMAT,
407 p2i(archived), p2i(new_p));
408
409 // Add the klass to the list of classes that need to be loaded before
410 // module system initialization
411 Klass *orig_k = obj->klass();
412 Klass *relocated_k = archived->klass();
413 _subgraph_info->add_subgraph_object_klass(orig_k, relocated_k);
414 }
463 oop archived_m = MetaspaceShared::find_archived_heap_object(m);
464 if (CompressedOops::is_null(archived_m)) {
465 return;
466 }
467
468 if (field_type == T_OBJECT) {
469 // obtain k's subGraph Info
470 KlassSubGraphInfo* subgraph_info = get_subgraph_info(k);
471
472 // get the object referenced by the field
473 oop f = m->obj_field(field_offset);
474 if (!CompressedOops::is_null(f)) {
475 LogTarget(Debug, cds, heap) log;
476 LogStream ls(log);
477 outputStream* out = &ls;
478 log.print("Start from: ");
479 f->print_on(out);
480
481 // get the archived copy of the field referenced object
482 oop af = MetaspaceShared::archive_heap_object(f, THREAD);
483 if (!MetaspaceShared::is_archive_object(f)) {
484 WalkOopAndArchiveClosure walker(1, subgraph_info, f, af);
485 f->oop_iterate(&walker);
486 }
487
488 // The field value is not preserved in the archived mirror.
489 // Record the field as a new subGraph entry point. The recorded
490 // information is restored from the archive at runtime.
491 subgraph_info->add_subgraph_entry_field(field_offset, af);
492 Klass *relocated_k = af->klass();
493 Klass *orig_k = f->klass();
494 subgraph_info->add_subgraph_object_klass(orig_k, relocated_k);
495 } else {
496 // The field contains null, we still need to record the entry point,
497 // so it can be restored at runtime.
498 subgraph_info->add_subgraph_entry_field(field_offset, NULL);
499 }
500 } else {
501 ShouldNotReachHere();
502 }
503 }
504
505 #define do_module_object_graph(archive_object_graph_do) \
506 archive_object_graph_do(SystemDictionary::ArchivedModuleGraph_klass(), jdk_internal_module_ArchivedModuleGraph::archivedSystemModules_offset(), T_OBJECT, CHECK); \
507 archive_object_graph_do(SystemDictionary::ArchivedModuleGraph_klass(), jdk_internal_module_ArchivedModuleGraph::archivedModuleFinder_offset(), T_OBJECT, CHECK); \
508 archive_object_graph_do(SystemDictionary::ArchivedModuleGraph_klass(), jdk_internal_module_ArchivedModuleGraph::archivedMainModule_offset(), T_OBJECT, CHECK); \
509 archive_object_graph_do(SystemDictionary::ArchivedModuleGraph_klass(), jdk_internal_module_ArchivedModuleGraph::archivedConfiguration_offset(), T_OBJECT, CHECK); \
510 archive_object_graph_do(SystemDictionary::ImmutableCollections_ListN_klass(), java_util_ImmutableCollections_ListN::EMPTY_LIST_offset(), T_OBJECT, CHECK); \
511 archive_object_graph_do(SystemDictionary::ImmutableCollections_MapN_klass(), java_util_ImmutableCollections_MapN::EMPTY_MAP_offset(), T_OBJECT, CHECK); \
512 archive_object_graph_do(SystemDictionary::ImmutableCollections_SetN_klass(), java_util_ImmutableCollections_SetN::EMPTY_SET_offset(), T_OBJECT, CHECK); \
513 archive_object_graph_do(SystemDictionary::Integer_IntegerCache_klass(), java_lang_Integer_IntegerCache::archivedCache_offset(), T_OBJECT, CHECK); \
514 archive_object_graph_do(SystemDictionary::Configuration_klass(), java_lang_module_Configuration::EMPTY_CONFIGURATION_offset(), T_OBJECT, CHECK)
|
335 int _level;
336 KlassSubGraphInfo* _subgraph_info;
337 oop _orig_referencing_obj;
338 oop _archived_referencing_obj;
339 public:
340 WalkOopAndArchiveClosure(int level, KlassSubGraphInfo* subgraph_info,
341 oop orig, oop archived) : _level(level),
342 _subgraph_info(subgraph_info),
343 _orig_referencing_obj(orig),
344 _archived_referencing_obj(archived) {}
345 void do_oop(narrowOop *p) { WalkOopAndArchiveClosure::do_oop_work(p); }
346 void do_oop( oop *p) { WalkOopAndArchiveClosure::do_oop_work(p); }
347
348 protected:
349 template <class T> void do_oop_work(T *p) {
350 oop obj = RawAccess<>::oop_load(p);
351 if (!CompressedOops::is_null(obj)) {
352 // A java.lang.Class instance can not be included in an archived
353 // object sub-graph.
354 if (java_lang_Class::is_instance(obj)) {
355 log_error(cds, heap)("Unknown java.lang.Class object is in the archived sub-graph\n");
356 vm_exit(1);
357 }
358
359 LogTarget(Debug, cds, heap) log;
360 LogStream ls(log);
361 outputStream* out = &ls;
362 {
363 ResourceMark rm;
364 log.print("(%d) %s <--- referenced from: %s",
365 _level, obj->klass()->external_name(),
366 CompressedOops::is_null(_orig_referencing_obj) ?
367 "" : _orig_referencing_obj->klass()->external_name());
368 obj->print_on(out);
369 }
370
371 if (MetaspaceShared::is_archive_object(obj)) {
372 // The current oop is an archived oop, nothing needs to be done
373 log.print("--- object is already archived ---");
374 return;
375 }
376
377 size_t field_delta = pointer_delta(
378 p, _orig_referencing_obj, sizeof(char));
379 T* new_p = (T*)(address(_archived_referencing_obj) + field_delta);
380 oop archived = MetaspaceShared::find_archived_heap_object(obj);
381 if (archived != NULL) {
382 // There is an archived copy existing, update reference to point
383 // to the archived copy
384 RawAccess<IS_NOT_NULL>::oop_store(new_p, archived);
385 log.print(
386 "--- found existing archived copy, store archived " PTR_FORMAT " in " PTR_FORMAT,
387 p2i(archived), p2i(new_p));
388 return;
389 }
390
391 int l = _level + 1;
392 Thread* THREAD = Thread::current();
393 // Archive the current oop before iterating through its references
394 archived = MetaspaceShared::archive_heap_object(obj, THREAD);
395 if (archived == NULL) {
396 ResourceMark rm;
397 LogTarget(Error, cds, heap) log_err;
398 LogStream ls_err(log_err);
399 outputStream* out_err = &ls_err;
400 log_err.print("Failed to archive %s object ("
401 PTR_FORMAT "), size[" SIZE_FORMAT "] in sub-graph",
402 obj->klass()->external_name(), p2i(obj), (size_t)obj->size());
403 obj->print_on(out_err);
404 vm_exit(1);
405 }
406 assert(MetaspaceShared::is_archive_object(archived), "must be archived");
407 log.print("=== archiving oop " PTR_FORMAT " ==> " PTR_FORMAT,
408 p2i(obj), p2i(archived));
409
410 // Following the references in the current oop and archive any
411 // encountered objects during the process
412 WalkOopAndArchiveClosure walker(l, _subgraph_info, obj, archived);
413 obj->oop_iterate(&walker);
414
415 // Update the reference in the archived copy of the referencing object
416 RawAccess<IS_NOT_NULL>::oop_store(new_p, archived);
417 log.print("=== store archived " PTR_FORMAT " in " PTR_FORMAT,
418 p2i(archived), p2i(new_p));
419
420 // Add the klass to the list of classes that need to be loaded before
421 // module system initialization
422 Klass *orig_k = obj->klass();
423 Klass *relocated_k = archived->klass();
424 _subgraph_info->add_subgraph_object_klass(orig_k, relocated_k);
425 }
474 oop archived_m = MetaspaceShared::find_archived_heap_object(m);
475 if (CompressedOops::is_null(archived_m)) {
476 return;
477 }
478
479 if (field_type == T_OBJECT) {
480 // obtain k's subGraph Info
481 KlassSubGraphInfo* subgraph_info = get_subgraph_info(k);
482
483 // get the object referenced by the field
484 oop f = m->obj_field(field_offset);
485 if (!CompressedOops::is_null(f)) {
486 LogTarget(Debug, cds, heap) log;
487 LogStream ls(log);
488 outputStream* out = &ls;
489 log.print("Start from: ");
490 f->print_on(out);
491
492 // get the archived copy of the field referenced object
493 oop af = MetaspaceShared::archive_heap_object(f, THREAD);
494 if (af == NULL) {
495 // Skip archiving the sub-graph referenced from the current entry field.
496 ResourceMark rm;
497 log_info(cds, heap)(
498 "Cannot archive the sub-graph referenced from %s object ("
499 PTR_FORMAT ") size[" SIZE_FORMAT "], skipped.",
500 f->klass()->external_name(), p2i(f), (size_t)f->size());
501 return;
502 }
503 if (!MetaspaceShared::is_archive_object(f)) {
504 WalkOopAndArchiveClosure walker(1, subgraph_info, f, af);
505 f->oop_iterate(&walker);
506 }
507
508 // The field value is not preserved in the archived mirror.
509 // Record the field as a new subGraph entry point. The recorded
510 // information is restored from the archive at runtime.
511 subgraph_info->add_subgraph_entry_field(field_offset, af);
512 Klass *relocated_k = af->klass();
513 Klass *orig_k = f->klass();
514 subgraph_info->add_subgraph_object_klass(orig_k, relocated_k);
515 ResourceMark rm;
516 log_info(cds, heap)(
517 "Archived the sub-graph referenced from %s object " PTR_FORMAT,
518 f->klass()->external_name(), p2i(f));
519 } else {
520 // The field contains null, we still need to record the entry point,
521 // so it can be restored at runtime.
522 subgraph_info->add_subgraph_entry_field(field_offset, NULL);
523 }
524 } else {
525 ShouldNotReachHere();
526 }
527 }
528
529 #define do_module_object_graph(archive_object_graph_do) \
530 archive_object_graph_do(SystemDictionary::ArchivedModuleGraph_klass(), jdk_internal_module_ArchivedModuleGraph::archivedSystemModules_offset(), T_OBJECT, CHECK); \
531 archive_object_graph_do(SystemDictionary::ArchivedModuleGraph_klass(), jdk_internal_module_ArchivedModuleGraph::archivedModuleFinder_offset(), T_OBJECT, CHECK); \
532 archive_object_graph_do(SystemDictionary::ArchivedModuleGraph_klass(), jdk_internal_module_ArchivedModuleGraph::archivedMainModule_offset(), T_OBJECT, CHECK); \
533 archive_object_graph_do(SystemDictionary::ArchivedModuleGraph_klass(), jdk_internal_module_ArchivedModuleGraph::archivedConfiguration_offset(), T_OBJECT, CHECK); \
534 archive_object_graph_do(SystemDictionary::ImmutableCollections_ListN_klass(), java_util_ImmutableCollections_ListN::EMPTY_LIST_offset(), T_OBJECT, CHECK); \
535 archive_object_graph_do(SystemDictionary::ImmutableCollections_MapN_klass(), java_util_ImmutableCollections_MapN::EMPTY_MAP_offset(), T_OBJECT, CHECK); \
536 archive_object_graph_do(SystemDictionary::ImmutableCollections_SetN_klass(), java_util_ImmutableCollections_SetN::EMPTY_SET_offset(), T_OBJECT, CHECK); \
537 archive_object_graph_do(SystemDictionary::Integer_IntegerCache_klass(), java_lang_Integer_IntegerCache::archivedCache_offset(), T_OBJECT, CHECK); \
538 archive_object_graph_do(SystemDictionary::Configuration_klass(), java_lang_module_Configuration::EMPTY_CONFIGURATION_offset(), T_OBJECT, CHECK)
|