RFR(S) 8208658: Make CDS archived heap regions usable even if compressed oop encoding has changed

Jiangli Zhou jiangli.zhou at oracle.com
Tue Aug 7 16:25:49 UTC 2018

Hi Ioi,

This is a welcomed change! Thanks for doing this. I'd like to suggest 
building a relocation table at dump time. The table can contain entries 
with pair of 'offset_to_region_start:narrow_oop_value'. Then at runtime, 
we can avoid iterating the objects. That would help to reduce the 
overhead that you are observing when relocation is needed at runtime. 
This could be done as a further optimization in a follow-up RFE for 12.

- src/hotspot/share/memory/heapShared.inline.hpp

- src/hotspot/share/memory/heapShared.cpp

   33 inline oop HeapShared::decode_not_null(narrowOop v) {
   34   assert(!CompressedOops::is_null(v), "narrow oop value can never 
be zero");
   35   oop result = (oop)(void*)((uintptr_t)_narrow_oop_base + 
((uintptr_t)v << _narrow_oop_shift));
   36   assert(check_obj_alignment(result), "address not aligned: " 
INTPTR_FORMAT, p2i((void*) result));
   37   return result;
   38 }

  510 void HeapShared::init_narrow_oop_decoding(address base, int shift) {
  511   _narrow_oop_base = base;
  512   _narrow_oop_shift = shift;
  513 }

- src/hotspot/share/memory/filemap.cpp

  913     //   dumptime heap end  ------------v
  914     //   [      |archived heap regions| ]         runtime heap end 
  915     //                                       [   |archived heap 
regions| ]
  916     // |<-----delta-------------------->|
  917     //
  918     // At dump time, the archived heap region were near the top of 
the heap.
  919     // At run time, that region may not be inside the heap, so we 
move it so
  920     // that it's now near the top of teh runtime time. This can be 
done by
  921     // the simple math of adding the delta as shown above.
  922     address dumptime_heap_end = (address)_header->_g1_reserved.end();
  923     address runtime_heap_end = 
  924     delta = runtime_heap_end - dumptime_heap_end;
  925   }
  927   HeapShared::init_narrow_oop_decoding(narrow_oop_base() + delta, 

1051 class RelocateInternalPointers: public BasicOopIterateClosure {
1056   virtual void do_oop(narrowOop *p) {
1057     narrowOop v = *p;
1058     if (!CompressedOops::is_null(v)) {
1059       oop o = HeapShared::decode_not_null(v);
1060       RawAccess<IS_NOT_NULL>::oop_store(p, o);
1061     }
1062   }

Your relocation change boils down to above sections of code. It works as 
both UnscaledNarrowOop encoding and ZeroBasedNarrowOop encoding use 0 as 
the base. I believe we don't handle heap based encoding with CDS 
enabled. Can you please double check that.

The new HeapShared::decode_not_null() decodes the narrowOop value using 
the dump time encoding mode with added base delta. Can you please rename 
it to be more descriptive, for example 
HeapShared::decode_with_archived_encoding_mode()? Please also add some 
comments to include these detail for this function.

- src/hotspot/share/memory/filemap.cpp

  886   if (narrow_klass_base() != Universe::narrow_klass_base() ||
  887       narrow_klass_shift() != Universe::narrow_klass_shift()) {
  888     log_info(cds)("Cached heap data from the CDS archive need to 
be relocated because");
  889     log_info(cds)("the CDS archive was created with an 
incompatible heap size: " UINTX_FORMAT "M.", max_heap_size()/M);
  890     log_info(cds)("Current narrow_klass_base = " PTR_FORMAT ", 
narrow_klass_shift = %d",
  891                   p2i(Universe::narrow_klass_base()), 
  892     return;
  893   }

Please fix the log message at 888 as relocation is not done in above case.

Please move the code at line 895 - 898 to be before the above code, so 
we still have the logging information about the dump time encoding modes 
when runtime narrow_klass_encoding is different. The dump time encoding 
modes are useful debugging information.

1039 void FileMapInfo::relocate_archived_heap_embedded_pointers()

1051 class RelocateInternalPointers: public BasicOopIterateClosure

1068 void FileMapInfo::relocate_archived_heap_embedded_pointers_impl

Could you please place above new code blocks in heapShared.* files? I 
filed JDK-8206009 to move all heap object archiving code to 
heapShared.*. It's helpful to make sure the related new code goes to the 
right files before we completely resolve existing code for JDK-8206009.

- src/hotspot/share/gc/g1/heapRegion.cpp

Can you please check the percentage of unused region space if we force 
8M gc region at dump time? The unused spaces in the archived heap 
regions are filled with dummy objects at runtime and cannot be utilized. 
It would also introduce gaps between the archived heap regions at 
runtime when the GC region size is < 8M with smaller heap size. We 
should check with GC team on this and see if there are other 
alternatives to resolve the overlapping issue. One possible solution I 
think is to relocate the 'open' archive heap region further down at 
runtime if the 'open' and 'closed' archive regions are in the same G1 
region at runtime.

- test/hotspot/jtreg/runtime/appcds/cacheObject/DifferentHeapSizes.java

Looks good! How about adding some scenarios with heap size > 32G as 
sanity checks.



On 8/1/18 11:04 PM, Ioi Lam wrote:
> https://bugs.openjdk.java.net/browse/JDK-8208658
> http://cr.openjdk.java.net/~iklam/jdk12/8208658-relocate-archived-heap-regions.v00/ 
>     At runtime, if you use a maximum heap size (-Xmx) setting that's
>     different than the one used at CDS archive creation time, the 
> archived
>     heap regions may fail to map. The reason is the archived heap regions
>     are hard-coded to a specific compressed oop encoding scheme.
>     This causes degradation in start-up time, because the archived heap
>     regions enable many aggressive optimizations, such as JDK-8202035,
>     archiving the system module info.
>     This degradation is undesirable for JDK-8204247 (include default
>     CDS archive in JDK binary) -- what we want is to ship a CDS archive
>     that's optimal regardless of the max heap settings.
> FIX:
>     If the compressed oop encoding scheme is different:
>         - relocate the archived heap regions so it
>           fits within the runtime heap bounds.
>         - patch all reference fields in the archived objects to
>           use the runtime compressed oop encoding scheme.
>     # dump archive
>     java -Xshare:dump -Xmx2000m
>     # same compressed oop encoding
>     java -Xshare:on -Xmx2000m -Xlog:cds -version
>     # different compressed oop encoding
>     java -Xshare:on -Xmx2090m -Xlog:cds -version
>     Note: the archive is dumped with UnscaledNarrowOop encoding.
>     At run time, if -Xmx2090m is specified, ZeroBasedNarrowOop is
>     used instead.
> ========================================================================
>     OLD same encoding      34.45 ms +- 0.51%
>     OLD diff encoding      47.76 ms +- 0.94%  <<<<< 13.3 ms degradation!
>     NEW same encoding      34.58 ms +- 0.61%
>     NEW diff encoding      35.09 ms +- 0.24% <<<<< 0.5 ms degradation
> ========================================================================
>     The cost of relocating/patching the archived heap regions is only
>     0.5 ms. This is much better than the 13.3 ms degradation caused by 
> the
>     failure to map the archived heap regions.
>     All 150+ CDS tests passed locally. I am starting tiers 1/2/3 runs.
> Thanks
> - Ioi

More information about the hotspot-runtime-dev mailing list