1 // Copyright 2021 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_HEAP_LINEAR_ALLOCATION_AREA_H_ 6 #define V8_HEAP_LINEAR_ALLOCATION_AREA_H_ 7 8 // This header file is included outside of src/heap/. 9 // Avoid including src/heap/ internals. 10 #include "include/v8-internal.h" 11 #include "src/common/checks.h" 12 13 namespace v8 { 14 namespace internal { 15 16 // A linear allocation area to allocate objects from. 17 // 18 // Invariant that must hold at all times: 19 // start <= top <= limit 20 class LinearAllocationArea final { 21 public: 22 LinearAllocationArea() = default; LinearAllocationArea(Address top,Address limit)23 LinearAllocationArea(Address top, Address limit) 24 : start_(top), top_(top), limit_(limit) { 25 Verify(); 26 } 27 Reset(Address top,Address limit)28 void Reset(Address top, Address limit) { 29 start_ = top; 30 top_ = top; 31 limit_ = limit; 32 Verify(); 33 } 34 ResetStart()35 void ResetStart() { start_ = top_; } 36 CanIncrementTop(size_t bytes)37 V8_INLINE bool CanIncrementTop(size_t bytes) { 38 Verify(); 39 return (top_ + bytes) <= limit_; 40 } 41 IncrementTop(size_t bytes)42 V8_INLINE Address IncrementTop(size_t bytes) { 43 Address old_top = top_; 44 top_ += bytes; 45 Verify(); 46 return old_top; 47 } 48 DecrementTopIfAdjacent(Address new_top,size_t bytes)49 V8_INLINE bool DecrementTopIfAdjacent(Address new_top, size_t bytes) { 50 Verify(); 51 if ((new_top + bytes) == top_) { 52 top_ = new_top; 53 if (start_ > top_) { 54 ResetStart(); 55 } 56 Verify(); 57 return true; 58 } 59 return false; 60 } 61 MergeIfAdjacent(LinearAllocationArea & other)62 V8_INLINE bool MergeIfAdjacent(LinearAllocationArea& other) { 63 Verify(); 64 other.Verify(); 65 if (top_ == other.limit_) { 66 top_ = other.top_; 67 start_ = other.start_; 68 other.Reset(kNullAddress, kNullAddress); 69 Verify(); 70 return true; 71 } 72 return false; 73 } 74 SetLimit(Address limit)75 V8_INLINE void SetLimit(Address limit) { 76 limit_ = limit; 77 Verify(); 78 } 79 start()80 V8_INLINE Address start() const { 81 Verify(); 82 return start_; 83 } top()84 V8_INLINE Address top() const { 85 Verify(); 86 return top_; 87 } limit()88 V8_INLINE Address limit() const { 89 Verify(); 90 return limit_; 91 } top_address()92 const Address* top_address() const { return &top_; } top_address()93 Address* top_address() { return &top_; } limit_address()94 const Address* limit_address() const { return &limit_; } limit_address()95 Address* limit_address() { return &limit_; } 96 Verify()97 void Verify() const { 98 #ifdef DEBUG 99 SLOW_DCHECK(start_ <= top_); 100 SLOW_DCHECK(top_ <= limit_); 101 SLOW_DCHECK(top_ == kNullAddress || (top_ & kHeapObjectTagMask) == 0); 102 #endif // DEBUG 103 } 104 105 static constexpr int kSize = 3 * kSystemPointerSize; 106 107 private: 108 // The start of the LAB. Initially coincides with `top_`. As top is moved 109 // ahead, the area [start_, top_[ denotes a range of new objects. This range 110 // is reset with `ResetStart()`. 111 Address start_ = kNullAddress; 112 // The top of the LAB that is used for allocation. 113 Address top_ = kNullAddress; 114 // Limit of the LAB the denotes the end of the valid range for allocation. 115 Address limit_ = kNullAddress; 116 }; 117 118 static_assert(sizeof(LinearAllocationArea) == LinearAllocationArea::kSize, 119 "LinearAllocationArea's size must be small because it " 120 "is included in IsolateData."); 121 122 } // namespace internal 123 } // namespace v8 124 125 #endif // V8_HEAP_LINEAR_ALLOCATION_AREA_H_ 126