1 /*
  2  * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 #include "precompiled.hpp"
 25 #include "gc/shared/slidingForwarding.inline.hpp"
 26 #include "oops/markWord.hpp"
 27 #include "oops/oop.inline.hpp"
 28 #include "utilities/align.hpp"
 29 #include "unittest.hpp"
 30 
 31 #ifdef _LP64
 32 #ifndef PRODUCT
 33 
 34 static uintptr_t make_mark(uintptr_t target_region, uintptr_t offset) {
 35   return (target_region) << 3 | (offset << 4) | 3 /* forwarded */;
 36 }
 37 
 38 static uintptr_t make_fallback() {
 39   return ((uintptr_t(1) << 2) /* fallback */ | 3 /* forwarded */);
 40 }
 41 
 42 // Test simple forwarding within the same region.
 43 TEST_VM(SlidingForwarding, simple) {
 44   HeapWord fakeheap[32] = { nullptr };
 45   HeapWord* heap = align_up(fakeheap, 8 * sizeof(HeapWord));
 46   oop obj1 = cast_to_oop(&heap[2]);
 47   oop obj2 = cast_to_oop(&heap[0]);
 48   SlidingForwarding::initialize(MemRegion(&heap[0], &heap[16]), 8);
 49   obj1->set_mark(markWord::prototype());
 50   SlidingForwarding::begin();
 51 
 52   SlidingForwarding::forward_to(obj1, obj2);
 53   ASSERT_EQ(obj1->mark().value(), make_mark(0 /* target_region */, 0 /* offset */));
 54   ASSERT_EQ(SlidingForwarding::forwardee(obj1), obj2);
 55 
 56   SlidingForwarding::end();
 57 }
 58 
 59 // Test forwardings crossing 2 regions.
 60 TEST_VM(SlidingForwarding, tworegions) {
 61   HeapWord fakeheap[32] = { nullptr };
 62   HeapWord* heap = align_up(fakeheap, 8 * sizeof(HeapWord));
 63   oop obj1 = cast_to_oop(&heap[14]);
 64   oop obj2 = cast_to_oop(&heap[2]);
 65   oop obj3 = cast_to_oop(&heap[10]);
 66   SlidingForwarding::initialize(MemRegion(&heap[0], &heap[16]), 8);
 67   obj1->set_mark(markWord::prototype());
 68   SlidingForwarding::begin();
 69 
 70   SlidingForwarding::forward_to(obj1, obj2);
 71   ASSERT_EQ(obj1->mark().value(), make_mark(0 /* target_region */, 2 /* offset */));
 72   ASSERT_EQ(SlidingForwarding::forwardee(obj1), obj2);
 73 
 74   SlidingForwarding::forward_to(obj1, obj3);
 75   ASSERT_EQ(obj1->mark().value(), make_mark(1 /* target_region */, 2 /* offset */));
 76   ASSERT_EQ(SlidingForwarding::forwardee(obj1), obj3);
 77 
 78   SlidingForwarding::end();
 79 }
 80 
 81 // Test fallback forwardings crossing 4 regions.
 82 TEST_VM(SlidingForwarding, fallback) {
 83   HeapWord fakeheap[32] = { nullptr };
 84   HeapWord* heap = align_up(fakeheap, 8 * sizeof(HeapWord));
 85   oop s_obj1 = cast_to_oop(&heap[12]);
 86   oop s_obj2 = cast_to_oop(&heap[13]);
 87   oop s_obj3 = cast_to_oop(&heap[14]);
 88   oop s_obj4 = cast_to_oop(&heap[15]);
 89   oop t_obj1 = cast_to_oop(&heap[2]);
 90   oop t_obj2 = cast_to_oop(&heap[4]);
 91   oop t_obj3 = cast_to_oop(&heap[10]);
 92   oop t_obj4 = cast_to_oop(&heap[12]);
 93   SlidingForwarding::initialize(MemRegion(&heap[0], &heap[16]), 4);
 94   s_obj1->set_mark(markWord::prototype());
 95   s_obj2->set_mark(markWord::prototype());
 96   s_obj3->set_mark(markWord::prototype());
 97   s_obj4->set_mark(markWord::prototype());
 98   SlidingForwarding::begin();
 99 
100   SlidingForwarding::forward_to(s_obj1, t_obj1);
101   ASSERT_EQ(s_obj1->mark().value(), make_mark(0 /* target_region */, 2 /* offset */));
102   ASSERT_EQ(SlidingForwarding::forwardee(s_obj1), t_obj1);
103 
104   SlidingForwarding::forward_to(s_obj2, t_obj2);
105   ASSERT_EQ(s_obj2->mark().value(), make_mark(1 /* target_region */, 0 /* offset */));
106   ASSERT_EQ(SlidingForwarding::forwardee(s_obj2), t_obj2);
107 
108   SlidingForwarding::forward_to(s_obj3, t_obj3);
109   ASSERT_EQ(s_obj3->mark().value(), make_fallback());
110   ASSERT_EQ(SlidingForwarding::forwardee(s_obj3), t_obj3);
111 
112   SlidingForwarding::forward_to(s_obj4, t_obj4);
113   ASSERT_EQ(s_obj4->mark().value(), make_fallback());
114   ASSERT_EQ(SlidingForwarding::forwardee(s_obj4), t_obj4);
115 
116   SlidingForwarding::end();
117 }
118 
119 #endif // PRODUCT
120 #endif // _LP64