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 #include "include/v8-internal.h"
9 #include "src/common/checks.h"
10 
11 namespace v8 {
12 namespace internal {
13 
14 // A linear allocation area to allocate objects from.
15 //
16 // Invariant that must hold at all times:
17 //   start <= top <= limit
18 class LinearAllocationArea final {
19  public:
20   LinearAllocationArea() = default;
LinearAllocationArea(Address top,Address limit)21   LinearAllocationArea(Address top, Address limit)
22       : start_(top), top_(top), limit_(limit) {
23     Verify();
24   }
25 
Reset(Address top,Address limit)26   void Reset(Address top, Address limit) {
27     start_ = top;
28     top_ = top;
29     limit_ = limit;
30     Verify();
31   }
32 
ResetStart()33   void ResetStart() { start_ = top_; }
34 
CanIncrementTop(size_t bytes)35   V8_INLINE bool CanIncrementTop(size_t bytes) {
36     Verify();
37     return (top_ + bytes) <= limit_;
38   }
39 
IncrementTop(size_t bytes)40   V8_INLINE Address IncrementTop(size_t bytes) {
41     Address old_top = top_;
42     top_ += bytes;
43     Verify();
44     return old_top;
45   }
46 
DecrementTopIfAdjacent(Address new_top,size_t bytes)47   V8_INLINE bool DecrementTopIfAdjacent(Address new_top, size_t bytes) {
48     Verify();
49     if ((new_top + bytes) == top_) {
50       top_ = new_top;
51       if (start_ > top_) {
52         ResetStart();
53       }
54       Verify();
55       return true;
56     }
57     return false;
58   }
59 
MergeIfAdjacent(LinearAllocationArea & other)60   V8_INLINE bool MergeIfAdjacent(LinearAllocationArea& other) {
61     Verify();
62     other.Verify();
63     if (top_ == other.limit_) {
64       top_ = other.top_;
65       start_ = other.start_;
66       other.Reset(kNullAddress, kNullAddress);
67       Verify();
68       return true;
69     }
70     return false;
71   }
72 
SetLimit(Address limit)73   V8_INLINE void SetLimit(Address limit) {
74     limit_ = limit;
75     Verify();
76   }
77 
start()78   V8_INLINE Address start() const {
79     Verify();
80     return start_;
81   }
top()82   V8_INLINE Address top() const {
83     Verify();
84     return top_;
85   }
limit()86   V8_INLINE Address limit() const {
87     Verify();
88     return limit_;
89   }
top_address()90   const Address* top_address() const { return &top_; }
top_address()91   Address* top_address() { return &top_; }
limit_address()92   const Address* limit_address() const { return &limit_; }
limit_address()93   Address* limit_address() { return &limit_; }
94 
Verify()95   void Verify() const {
96 #ifdef DEBUG
97     SLOW_DCHECK(start_ <= top_);
98     SLOW_DCHECK(top_ <= limit_);
99     SLOW_DCHECK(top_ == kNullAddress || (top_ & kHeapObjectTagMask) == 0);
100 #endif  // DEBUG
101   }
102 
103  private:
104   // The start of the LAB. Initially coincides with `top_`. As top is moved
105   // ahead, the area [start_, top_[ denotes a range of new objects. This range
106   // is reset with `ResetStart()`.
107   Address start_ = kNullAddress;
108   // The top of the LAB that is used for allocation.
109   Address top_ = kNullAddress;
110   // Limit of the LAB the denotes the end of the valid range for allocation.
111   Address limit_ = kNullAddress;
112 };
113 
114 }  // namespace internal
115 }  // namespace v8
116 
117 #endif  // V8_HEAP_LINEAR_ALLOCATION_AREA_H_
118