< prev index next >

src/hotspot/share/gc/z/zRelocate.cpp

Print this page
@@ -321,23 +321,26 @@
  
  static zaddress relocate_object_inner(ZForwarding* forwarding, zaddress from_addr, ZForwardingCursor* cursor) {
    assert(ZHeap::heap()->is_object_live(from_addr), "Should be live");
  
    // Allocate object
-   const size_t size = ZUtils::object_size(from_addr);
+   const size_t old_size = ZUtils::object_size(from_addr);
+   const size_t size = ZUtils::copy_size(from_addr, old_size);
  
    ZAllocatorForRelocation* allocator = ZAllocator::relocation(forwarding->to_age());
  
    const zaddress to_addr = allocator->alloc_object(size);
  
    if (is_null(to_addr)) {
      // Allocation failed
      return zaddress::null;
    }
+   assert(to_addr != from_addr, "addresses must be different");
  
    // Copy object
-   ZUtils::object_copy_disjoint(from_addr, to_addr, size);
+   ZUtils::object_copy_disjoint(from_addr, to_addr, old_size);
+   ZUtils::initialize_hash_if_necessary(to_addr, from_addr);
  
    // Insert forwarding
    const zaddress to_addr_final = forwarding->insert(from_addr, to_addr, cursor);
  
    if (to_addr_final != to_addr) {

@@ -585,15 +588,17 @@
      } else {
        _other_compacted += aligned_size;
      }
    }
  
-   zaddress try_relocate_object_inner(zaddress from_addr) {
+   zaddress try_relocate_object_inner(zaddress from_addr, size_t old_size) {
      ZForwardingCursor cursor;
- 
-     const size_t size = ZUtils::object_size(from_addr);
      ZPage* const to_page = target(_forwarding->to_age());
+     zoffset_end from_offset = to_zoffset_end(ZAddress::offset(from_addr));
+     zoffset_end top = to_page != nullptr ? to_page->top() : to_zoffset_end(0);
+     const size_t new_size = ZUtils::copy_size(from_addr, old_size);
+     const size_t size = top == from_offset ? old_size : new_size;
  
      // Lookup forwarding
      {
        const zaddress to_addr = _forwarding->find(from_addr, &cursor);
        if (!is_null(to_addr)) {

@@ -607,17 +612,24 @@
      const zaddress allocated_addr = _allocator->alloc_object(to_page, size);
      if (is_null(allocated_addr)) {
        // Allocation failed
        return zaddress::null;
      }
+     if (old_size != new_size && ((top == from_offset) != (allocated_addr == from_addr))) {
+       _allocator->undo_alloc_object(to_page, allocated_addr, size);
+       return zaddress::null;
+     }
  
      // Copy object. Use conjoint copying if we are relocating
      // in-place and the new object overlaps with the old object.
-     if (_forwarding->in_place_relocation() && allocated_addr + size > from_addr) {
-       ZUtils::object_copy_conjoint(from_addr, allocated_addr, size);
+     if (_forwarding->in_place_relocation() && allocated_addr + old_size > from_addr) {
+       ZUtils::object_copy_conjoint(from_addr, allocated_addr, old_size);
      } else {
-       ZUtils::object_copy_disjoint(from_addr, allocated_addr, size);
+       ZUtils::object_copy_disjoint(from_addr, allocated_addr, old_size);
+     }
+     if (from_addr != allocated_addr) {
+       ZUtils::initialize_hash_if_necessary(allocated_addr, from_addr);
      }
  
      // Insert forwarding
      const zaddress to_addr = _forwarding->insert(from_addr, allocated_addr, &cursor);
      if (to_addr != allocated_addr) {

@@ -627,11 +639,11 @@
      }
  
      return to_addr;
    }
  
-   void update_remset_old_to_old(zaddress from_addr, zaddress to_addr) const {
+   void update_remset_old_to_old(zaddress from_addr, zaddress to_addr, size_t size) const {
      // Old-to-old relocation - move existing remset bits
  
      // If this is called for an in-place relocated page, then this code has the
      // responsibility to clear the old remset bits. Extra care is needed because:
      //

@@ -649,14 +661,12 @@
  
      // Uses _relaxed version to handle that in-place relocation resets _top
      assert(ZHeap::heap()->is_in_page_relaxed(from_page, from_addr), "Must be");
      assert(to_page->is_in(to_addr), "Must be");
  
- 
-     // Read the size from the to-object, since the from-object
-     // could have been overwritten during in-place relocation.
-     const size_t size = ZUtils::object_size(to_addr);
+     assert(size <= ZUtils::object_size(to_addr), "old size must be <= new size");
+     assert(size > 0, "size must be set");
  
      // If a young generation collection started while the old generation
      // relocated  objects, the remember set bits were flipped from "current"
      // to "previous".
      //

@@ -777,34 +787,35 @@
  
    void update_remset_promoted(zaddress to_addr) const {
      ZIterator::basic_oop_iterate(to_oop(to_addr), update_remset_promoted_filter_and_remap_per_field);
    }
  
-   void update_remset_for_fields(zaddress from_addr, zaddress to_addr) const {
+   void update_remset_for_fields(zaddress from_addr, zaddress to_addr, size_t size) const {
      if (_forwarding->to_age() != ZPageAge::old) {
        // No remembered set in young pages
        return;
      }
  
      // Need to deal with remset when moving objects to the old generation
      if (_forwarding->from_age() == ZPageAge::old) {
-       update_remset_old_to_old(from_addr, to_addr);
+       update_remset_old_to_old(from_addr, to_addr, size);
        return;
      }
  
      // Normal promotion
      update_remset_promoted(to_addr);
    }
  
    bool try_relocate_object(zaddress from_addr) {
-     const zaddress to_addr = try_relocate_object_inner(from_addr);
+     size_t size = ZUtils::object_size(from_addr);
+     const zaddress to_addr = try_relocate_object_inner(from_addr, size);
  
      if (is_null(to_addr)) {
        return false;
      }
  
-     update_remset_for_fields(from_addr, to_addr);
+     update_remset_for_fields(from_addr, to_addr, size);
  
      return true;
    }
  
    void start_in_place_relocation_prepare_remset(ZPage* from_page) {
< prev index next >