this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include "heap.h"
3
4#include <cstring>
5
6#include "frame.h"
7#include "objects.h"
8#include "runtime.h"
9#include "visitor.h"
10
11namespace py {
12
13Heap::Heap(word size) {
14 space_ = new Space(size);
15 immortal_ = new Space(size);
16}
17
18Heap::~Heap() {
19 delete space_;
20 delete immortal_;
21}
22
23NEVER_INLINE bool Heap::allocateRetry(word size, uword* address_out) {
24 // Since the allocation failed, invoke the garbage collector and retry.
25 collectGarbage();
26 return space_->allocate(size, address_out);
27}
28
29bool Heap::allocateImmortal(word size, uword* address_out) {
30 DCHECK(Utils::isAligned(size, kPointerSize), "request %ld not aligned", size);
31 if (UNLIKELY(!immortal_->allocate(size, address_out))) {
32 return allocateRetry(size, address_out);
33 }
34 return true;
35}
36
37bool Heap::contains(uword address) {
38 return space_->contains(address) || immortal_->contains(address);
39}
40
41void Heap::collectGarbage() { Thread::current()->runtime()->collectGarbage(); }
42
43bool Heap::verifySpace(Space* space) {
44 uword scan = space->start();
45 while (scan < space->fill()) {
46 if (!(*reinterpret_cast<RawObject*>(scan)).isHeader()) {
47 // Skip immediate values for alignment padding or header overflow.
48 scan += kPointerSize;
49 } else {
50 RawHeapObject object = HeapObject::fromAddress(scan + RawHeader::kSize);
51 // Objects start before the start of the space they are allocated in.
52 if (object.baseAddress() < space->start()) {
53 return false;
54 }
55 // Objects must have their instance data after their header.
56 if (object.address() < object.baseAddress()) {
57 return false;
58 }
59 // Objects cannot start after the end of the space they are allocated in.
60 if (object.address() > space->fill()) {
61 return false;
62 }
63 // Objects cannot end after the end of the space they are allocated in.
64 uword end = object.baseAddress() + object.size();
65 if (end > space->fill()) {
66 return false;
67 }
68 // Scan pointers that follow the header word, if any.
69 if (!object.isRoot()) {
70 scan = end;
71 } else {
72 for (scan += RawHeader::kSize; scan < end; scan += kPointerSize) {
73 auto pointer = reinterpret_cast<RawObject*>(scan);
74 if ((*pointer).isHeapObject() &&
75 !inHeap(HeapObject::cast(*pointer).address())) {
76 return false;
77 }
78 }
79 }
80 }
81 }
82 return true;
83}
84
85void Heap::visitAllObjects(HeapObjectVisitor* visitor) {
86 visitSpace(immortal_, visitor);
87 visitSpace(space_, visitor);
88}
89
90void Heap::visitSpace(Space* space, HeapObjectVisitor* visitor) {
91 uword scan = space->start();
92 while (scan < space->fill()) {
93 if (!(*reinterpret_cast<RawObject*>(scan)).isHeader()) {
94 // Skip immediate values for alignment padding or header overflow.
95 scan += kPointerSize;
96 continue;
97 }
98 RawHeapObject object = HeapObject::fromAddress(scan + RawHeader::kSize);
99 visitor->visitHeapObject(object);
100 scan = object.baseAddress() + object.size();
101 }
102}
103
104} // namespace py