< prev index next >

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

Print this page
*** 322,23 ***
  
  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);
  
    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;
    }
  
    // Copy object
!   ZUtils::object_copy_disjoint(from_addr, to_addr, size);
  
    // Insert forwarding
    const zaddress to_addr_final = forwarding->insert(from_addr, to_addr, cursor);
  
    if (to_addr_final != to_addr) {
--- 322,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 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, 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) {

*** 586,15 ***
      } else {
        _other_compacted += aligned_size;
      }
    }
  
!   zaddress try_relocate_object_inner(zaddress from_addr) {
      ZForwardingCursor cursor;
- 
-     const size_t size = ZUtils::object_size(from_addr);
      ZPage* const to_page = target(_forwarding->to_age());
  
      // Lookup forwarding
      {
        const zaddress to_addr = _forwarding->find(from_addr, &cursor);
        if (!is_null(to_addr)) {
--- 589,17 ---
      } else {
        _other_compacted += aligned_size;
      }
    }
  
!   zaddress try_relocate_object_inner(zaddress from_addr, size_t old_size) {
      ZForwardingCursor cursor;
      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)) {

*** 608,17 ***
      const zaddress allocated_addr = _allocator->alloc_object(to_page, size);
      if (is_null(allocated_addr)) {
        // Allocation failed
        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);
      } else {
!       ZUtils::object_copy_disjoint(from_addr, allocated_addr, size);
      }
  
      // Insert forwarding
      const zaddress to_addr = _forwarding->insert(from_addr, allocated_addr, &cursor);
      if (to_addr != allocated_addr) {
--- 613,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 + old_size > from_addr) {
!       ZUtils::object_copy_conjoint(from_addr, allocated_addr, old_size);
      } else {
!       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) {

*** 628,11 ***
      }
  
      return to_addr;
    }
  
!   void update_remset_old_to_old(zaddress from_addr, zaddress to_addr) 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:
      //
--- 640,11 ---
      }
  
      return to_addr;
    }
  
!   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:
      //

*** 650,14 ***
  
      // 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);
  
      // If a young generation collection started while the old generation
      // relocated  objects, the remember set bits were flipped from "current"
      // to "previous".
      //
--- 662,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");
  
!     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".
      //

*** 778,34 ***
  
    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 {
      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);
        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);
  
      if (is_null(to_addr)) {
        return false;
      }
  
!     update_remset_for_fields(from_addr, to_addr);
  
      return true;
    }
  
    void start_in_place_relocation_prepare_remset(ZPage* from_page) {
--- 788,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, 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, size);
        return;
      }
  
      // Normal promotion
      update_remset_promoted(to_addr);
    }
  
    bool try_relocate_object(zaddress 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, size);
  
      return true;
    }
  
    void start_in_place_relocation_prepare_remset(ZPage* from_page) {
< prev index next >