24
#include "precompiled.hpp"
25
#include "gc/x/xAddress.inline.hpp"
26
#include "gc/x/xForwarding.inline.hpp"
27
#include "gc/x/xForwardingAllocator.inline.hpp"
28
#include "gc/x/xGlobals.hpp"
29
#include "gc/x/xPage.inline.hpp"
30
#include "unittest.hpp"
32
using namespace testing;
34
#define CAPTURE_DELIM "\n"
35
#define CAPTURE1(expression) #expression << " evaluates to " << expression
36
#define CAPTURE2(e0, e1) CAPTURE1(e0) << CAPTURE_DELIM << CAPTURE1(e1)
38
#define CAPTURE(expression) CAPTURE1(expression)
40
class XForwardingTest : public Test {
44
class SequenceToFromIndex : AllStatic {
46
static uintptr_t even(size_t sequence_number) {
47
return sequence_number * 2;
49
static uintptr_t odd(size_t sequence_number) {
50
return even(sequence_number) + 1;
52
static uintptr_t one_to_one(size_t sequence_number) {
53
return sequence_number;
59
static void setup(XForwarding* forwarding) {
60
EXPECT_PRED1(is_power_of_2<size_t>, forwarding->_entries.length()) << CAPTURE(forwarding->_entries.length());
63
static void find_empty(XForwarding* forwarding) {
64
size_t size = forwarding->_entries.length();
65
size_t entries_to_check = size * 2;
67
for (size_t i = 0; i < entries_to_check; i++) {
68
uintptr_t from_index = SequenceToFromIndex::one_to_one(i);
70
XForwardingCursor cursor;
71
XForwardingEntry entry = forwarding->find(from_index, &cursor);
72
EXPECT_FALSE(entry.populated()) << CAPTURE2(from_index, size);
76
static void find_full(XForwarding* forwarding) {
77
size_t size = forwarding->_entries.length();
78
size_t entries_to_populate = size;
81
for (size_t i = 0; i < entries_to_populate; i++) {
82
uintptr_t from_index = SequenceToFromIndex::one_to_one(i);
84
XForwardingCursor cursor;
85
XForwardingEntry entry = forwarding->find(from_index, &cursor);
86
ASSERT_FALSE(entry.populated()) << CAPTURE2(from_index, size);
88
forwarding->insert(from_index, from_index, &cursor);
92
for (size_t i = 0; i < entries_to_populate; i++) {
93
uintptr_t from_index = SequenceToFromIndex::one_to_one(i);
95
XForwardingCursor cursor;
96
XForwardingEntry entry = forwarding->find(from_index, &cursor);
97
ASSERT_TRUE(entry.populated()) << CAPTURE2(from_index, size);
99
ASSERT_EQ(entry.from_index(), from_index) << CAPTURE(size);
100
ASSERT_EQ(entry.to_offset(), from_index) << CAPTURE(size);
104
static void find_every_other(XForwarding* forwarding) {
105
size_t size = forwarding->_entries.length();
106
size_t entries_to_populate = size / 2;
109
for (size_t i = 0; i < entries_to_populate; i++) {
110
uintptr_t from_index = SequenceToFromIndex::even(i);
112
XForwardingCursor cursor;
113
XForwardingEntry entry = forwarding->find(from_index, &cursor);
114
ASSERT_FALSE(entry.populated()) << CAPTURE2(from_index, size);
116
forwarding->insert(from_index, from_index, &cursor);
120
for (size_t i = 0; i < entries_to_populate; i++) {
121
uintptr_t from_index = SequenceToFromIndex::even(i);
123
XForwardingCursor cursor;
124
XForwardingEntry entry = forwarding->find(from_index, &cursor);
125
ASSERT_TRUE(entry.populated()) << CAPTURE2(from_index, size);
127
ASSERT_EQ(entry.from_index(), from_index) << CAPTURE(size);
128
ASSERT_EQ(entry.to_offset(), from_index) << CAPTURE(size);
135
for (size_t i = 0; i < entries_to_populate; i++) {
136
uintptr_t from_index = SequenceToFromIndex::odd(i);
138
XForwardingCursor cursor;
139
XForwardingEntry entry = forwarding->find(from_index, &cursor);
141
ASSERT_FALSE(entry.populated()) << CAPTURE2(from_index, size);
145
static void test(void (*function)(XForwarding*), uint32_t size) {
147
const XVirtualMemory vmem(0, XPageSizeSmall);
148
const XPhysicalMemory pmem(XPhysicalMemorySegment(0, XPageSizeSmall, true));
149
XPage page(XPageTypeSmall, vmem, pmem);
153
const size_t object_size = 16;
154
const uintptr_t object = page.alloc_object(object_size);
159
page.mark_object(XAddress::marked(object), dummy, dummy);
161
const uint32_t live_objects = size;
162
const size_t live_bytes = live_objects * object_size;
163
page.inc_live(live_objects, live_bytes);
166
XForwardingAllocator allocator;
167
const uint32_t nentries = XForwarding::nentries(&page);
168
allocator.reset((sizeof(XForwarding)) + (nentries * sizeof(XForwardingEntry)));
171
XForwarding* const forwarding = XForwarding::alloc(&allocator, &page);
174
(*function)(forwarding);
178
static void test(void (*function)(XForwarding*)) {
185
test(function, 1023);
186
test(function, 1024);
187
test(function, 1025);
191
TEST_F(XForwardingTest, setup) {
192
test(&XForwardingTest::setup);
195
TEST_F(XForwardingTest, find_empty) {
196
test(&XForwardingTest::find_empty);
199
TEST_F(XForwardingTest, find_full) {
200
test(&XForwardingTest::find_full);
203
TEST_F(XForwardingTest, find_every_other) {
204
test(&XForwardingTest::find_every_other);