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/gc_globals.hpp"
26 #include "gc/shared/slidingForwarding.inline.hpp"
27 #include "oops/markWord.hpp"
28 #include "oops/oop.inline.hpp"
29 #include "utilities/align.hpp"
30 #include "unittest.hpp"
31
32 #ifdef _LP64
33 #ifndef PRODUCT
34
35 static uintptr_t make_mark(uintptr_t target_region, uintptr_t offset) {
36 return (target_region) << 3 | (offset << 4) | 3 /* forwarded */;
37 }
38
39 static uintptr_t make_fallback() {
40 return ((uintptr_t(1) << 2) /* fallback */ | 3 /* forwarded */);
41 }
42
43 // Test simple forwarding within the same region.
44 TEST_VM(SlidingForwarding, simple) {
45 FlagSetting fs(UseAltGCForwarding, true);
46 HeapWord fakeheap[32] = { nullptr };
47 HeapWord* heap = align_up(fakeheap, 8 * sizeof(HeapWord));
48 oop obj1 = cast_to_oop(&heap[2]);
49 oop obj2 = cast_to_oop(&heap[0]);
50 SlidingForwarding::initialize(MemRegion(&heap[0], &heap[16]), 8);
51 obj1->set_mark(markWord::prototype());
52 SlidingForwarding::begin();
53
54 SlidingForwarding::forward_to<true>(obj1, obj2);
55 ASSERT_EQ(obj1->mark().value(), make_mark(0 /* target_region */, 0 /* offset */));
56 ASSERT_EQ(SlidingForwarding::forwardee<true>(obj1), obj2);
57
58 SlidingForwarding::end();
59 }
60
61 // Test forwardings crossing 2 regions.
62 TEST_VM(SlidingForwarding, tworegions) {
63 FlagSetting fs(UseAltGCForwarding, true);
64 HeapWord fakeheap[32] = { nullptr };
65 HeapWord* heap = align_up(fakeheap, 8 * sizeof(HeapWord));
66 oop obj1 = cast_to_oop(&heap[14]);
67 oop obj2 = cast_to_oop(&heap[2]);
68 oop obj3 = cast_to_oop(&heap[10]);
69 SlidingForwarding::initialize(MemRegion(&heap[0], &heap[16]), 8);
70 obj1->set_mark(markWord::prototype());
71 SlidingForwarding::begin();
72
73 SlidingForwarding::forward_to<true>(obj1, obj2);
74 ASSERT_EQ(obj1->mark().value(), make_mark(0 /* target_region */, 2 /* offset */));
75 ASSERT_EQ(SlidingForwarding::forwardee<true>(obj1), obj2);
76
77 SlidingForwarding::forward_to<true>(obj1, obj3);
78 ASSERT_EQ(obj1->mark().value(), make_mark(1 /* target_region */, 2 /* offset */));
79 ASSERT_EQ(SlidingForwarding::forwardee<true>(obj1), obj3);
80
81 SlidingForwarding::end();
82 }
83
84 // Test fallback forwardings crossing 4 regions.
85 TEST_VM(SlidingForwarding, fallback) {
86 FlagSetting fs(UseAltGCForwarding, true);
87 HeapWord fakeheap[32] = { nullptr };
88 HeapWord* heap = align_up(fakeheap, 8 * sizeof(HeapWord));
89 oop s_obj1 = cast_to_oop(&heap[12]);
90 oop s_obj2 = cast_to_oop(&heap[13]);
91 oop s_obj3 = cast_to_oop(&heap[14]);
92 oop s_obj4 = cast_to_oop(&heap[15]);
93 oop t_obj1 = cast_to_oop(&heap[2]);
94 oop t_obj2 = cast_to_oop(&heap[4]);
95 oop t_obj3 = cast_to_oop(&heap[10]);
96 oop t_obj4 = cast_to_oop(&heap[12]);
97 SlidingForwarding::initialize(MemRegion(&heap[0], &heap[16]), 4);
98 s_obj1->set_mark(markWord::prototype());
99 s_obj2->set_mark(markWord::prototype());
100 s_obj3->set_mark(markWord::prototype());
101 s_obj4->set_mark(markWord::prototype());
102 SlidingForwarding::begin();
103
104 SlidingForwarding::forward_to<true>(s_obj1, t_obj1);
105 ASSERT_EQ(s_obj1->mark().value(), make_mark(0 /* target_region */, 2 /* offset */));
106 ASSERT_EQ(SlidingForwarding::forwardee<true>(s_obj1), t_obj1);
107
108 SlidingForwarding::forward_to<true>(s_obj2, t_obj2);
109 ASSERT_EQ(s_obj2->mark().value(), make_mark(1 /* target_region */, 0 /* offset */));
110 ASSERT_EQ(SlidingForwarding::forwardee<true>(s_obj2), t_obj2);
111
112 SlidingForwarding::forward_to<true>(s_obj3, t_obj3);
113 ASSERT_EQ(s_obj3->mark().value(), make_fallback());
114 ASSERT_EQ(SlidingForwarding::forwardee<true>(s_obj3), t_obj3);
115
116 SlidingForwarding::forward_to<true>(s_obj4, t_obj4);
117 ASSERT_EQ(s_obj4->mark().value(), make_fallback());
118 ASSERT_EQ(SlidingForwarding::forwardee<true>(s_obj4), t_obj4);
119
120 SlidingForwarding::end();
121 }
122
123 #endif // PRODUCT
124 #endif // _LP64