this repo has no description
at trunk 104 lines 3.1 kB view raw
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