this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include "heap.h"
3
4#include "gtest/gtest.h"
5
6#include "globals.h"
7#include "os.h"
8#include "runtime.h"
9#include "test-utils.h"
10
11namespace py {
12namespace testing {
13
14using HeapTest = RuntimeFixture;
15
16TEST(HeapTestNoFixture, AllocateObjects) {
17 const int size = OS::kPageSize * 4;
18 Heap heap(size);
19
20 // Allocate the first half of the heap.
21 uword address1;
22 bool result1 = heap.allocate(size / 2, &address1);
23 ASSERT_TRUE(result1);
24 EXPECT_TRUE(heap.contains(address1));
25
26 // Allocate the second half of the heap.
27 uword address2;
28 bool result2 = heap.allocate(size / 2, &address2);
29 ASSERT_TRUE(result2);
30 EXPECT_TRUE(heap.contains(address2));
31}
32
33static RawObject createLargeStr(Heap* heap, word length) {
34 DCHECK(length > RawSmallStr::kMaxLength,
35 "string len %ld is too small to be a large string", length);
36 word size = LargeStr::allocationSize(length);
37 uword address;
38 CHECK(heap->allocate(size, &address), "out of memory");
39 return LargeStr::cast(
40 DataArray::initialize(address, length, LayoutId::kLargeStr));
41}
42
43TEST_F(HeapTest, AllocateFails) {
44 HandleScope scope(thread_);
45 Heap* heap = runtime_->heap();
46 word free_space = heap->space()->end() - heap->space()->fill();
47
48 // Allocate the first half of the heap. Use a handle to prevent gc
49 word first_half = Utils::roundUp(free_space / 2, kPointerSize * 2);
50 Object object1(&scope, createLargeStr(runtime_->heap(), first_half));
51 RawObject raw1 = *object1;
52 ASSERT_FALSE(raw1.isError());
53 EXPECT_TRUE(heap->contains(HeapObject::cast(raw1).address()));
54
55 // Try over allocating.
56 uword address2;
57 bool result2 = heap->allocate(free_space, &address2);
58 ASSERT_FALSE(result2);
59
60 // Allocate the second half of the heap.
61 word second_half = heap->space()->end() - heap->space()->fill();
62 uword address3;
63 bool result3 = heap->allocate(second_half, &address3);
64 ASSERT_TRUE(result3);
65 EXPECT_TRUE(heap->contains(address3));
66
67 ASSERT_EQ(heap->space()->end(), heap->space()->fill());
68}
69
70TEST_F(HeapTest, AllocateBigLargeInt) {
71 HandleScope scope(thread_);
72 Object result(&scope, runtime_->createLargeInt(100000));
73 ASSERT_TRUE(result.isLargeInt());
74 EXPECT_EQ(LargeInt::cast(*result).numDigits(), 100000);
75}
76
77TEST_F(HeapTest, AllocateImmortalPlacesObjectInImmortalSpace) {
78 Heap* heap = runtime_->heap();
79
80 uword address1;
81 bool result1 = heap->allocateImmortal(8, &address1);
82 ASSERT_TRUE(result1);
83 EXPECT_TRUE(heap->contains(address1));
84 EXPECT_TRUE(heap->isImmortal(address1));
85}
86
87TEST_F(HeapTest, AllocateBigInstance) {
88 HandleScope scope(thread_);
89 Layout layout(&scope, testing::layoutCreateEmpty(thread_));
90 Object result(&scope, runtime_->newInstanceWithSize(layout.id(),
91 100000 * kPointerSize));
92 ASSERT_TRUE(result.isInstance());
93 EXPECT_EQ(Instance::cast(*result).headerCountOrOverflow(), 100000);
94}
95
96class DummyVisitor : public HeapObjectVisitor {
97 public:
98 explicit DummyVisitor() : count_(0) {}
99
100 void visitHeapObject(RawHeapObject obj) {
101 visited_.push_back(obj);
102 count_++;
103 }
104
105 word count() { return count_; }
106
107 bool visited(RawObject obj) {
108 for (word i = 0; i < visited_.size(); i++) {
109 if (visited_[i] == obj) return true;
110 }
111 return false;
112 }
113
114 private:
115 Vector<RawObject> visited_;
116 word count_;
117};
118
119TEST(HeapTestNoFixture, VisitAllObjectsVisitsAllObjects) {
120 Heap heap(OS::kPageSize * 4);
121 DummyVisitor visitor;
122 EXPECT_EQ(visitor.count(), 0);
123 heap.visitAllObjects(&visitor);
124 EXPECT_EQ(visitor.count(), 0);
125 RawObject obj1 = createLargeStr(&heap, 10);
126 RawObject obj2 = createLargeStr(&heap, 10);
127 RawObject obj3 = createLargeStr(&heap, 10);
128 heap.visitAllObjects(&visitor);
129 EXPECT_TRUE(visitor.visited(obj1));
130 EXPECT_TRUE(visitor.visited(obj2));
131 EXPECT_TRUE(visitor.visited(obj3));
132 EXPECT_EQ(visitor.count(), 3);
133}
134
135} // namespace testing
136} // namespace py