• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifndef PANDA_RUNTIME_MEM_REGION_SPACE_INL_H
16 #define PANDA_RUNTIME_MEM_REGION_SPACE_INL_H
17 
18 #include "runtime/mem/region_space.h"
19 #include "libpandabase/utils/asan_interface.h"
20 
21 namespace panda::mem {
22 
23 class RegionAllocCheck {
24 public:
RegionAllocCheck(Region * region)25     explicit RegionAllocCheck(Region *region) : region_(region)
26     {
27         ASSERT(region_->SetAllocating(true));
28     }
~RegionAllocCheck()29     ~RegionAllocCheck()
30     {
31         ASSERT(region_->SetAllocating(false));
32     }
33     NO_COPY_SEMANTIC(RegionAllocCheck);
34     NO_MOVE_SEMANTIC(RegionAllocCheck);
35 
36 private:
37     Region *region_ FIELD_UNUSED;
38 };
39 
40 class RegionIterateCheck {
41 public:
RegionIterateCheck(Region * region)42     explicit RegionIterateCheck(Region *region) : region_(region)
43     {
44         ASSERT(region_->SetIterating(true));
45     }
~RegionIterateCheck()46     ~RegionIterateCheck()
47     {
48         ASSERT(region_->SetIterating(false));
49     }
50     NO_COPY_SEMANTIC(RegionIterateCheck);
51     NO_MOVE_SEMANTIC(RegionIterateCheck);
52 
53 private:
54     Region *region_ FIELD_UNUSED;
55 };
56 
57 template <bool atomic>
Alloc(size_t aligned_size)58 void *Region::Alloc(size_t aligned_size)
59 {
60     RegionAllocCheck alloc(this);
61     ASSERT(AlignUp(aligned_size, DEFAULT_ALIGNMENT_IN_BYTES) == aligned_size);
62     ASSERT(!IsTLAB());
63     uintptr_t old_top;
64     uintptr_t new_top;
65     if (atomic) {
66         auto atomic_top = reinterpret_cast<std::atomic<uintptr_t> *>(&top_);
67         // Atomic with relaxed order reason: data race with top_ with no synchronization or ordering constraints imposed
68         // on other reads or writes
69         old_top = atomic_top->load(std::memory_order_relaxed);
70         do {
71             new_top = old_top + aligned_size;
72             if (UNLIKELY(new_top > end_)) {
73                 return nullptr;
74             }
75         } while (!atomic_top->compare_exchange_weak(old_top, new_top, std::memory_order_relaxed));
76         ASAN_UNPOISON_MEMORY_REGION(ToVoidPtr(old_top), aligned_size);
77         return ToVoidPtr(old_top);
78     }
79     new_top = top_ + aligned_size;
80     if (UNLIKELY(new_top > end_)) {
81         return nullptr;
82     }
83     old_top = top_;
84     top_ = new_top;
85 
86     ASAN_UNPOISON_MEMORY_REGION(ToVoidPtr(old_top), aligned_size);
87     return ToVoidPtr(old_top);
88 }
89 
90 template <typename ObjectVisitor>
IterateOverObjects(const ObjectVisitor & visitor)91 void Region::IterateOverObjects(const ObjectVisitor &visitor)
92 {
93     // This method doesn't work for nonmovable regions
94     ASSERT(!HasFlag(RegionFlag::IS_NONMOVABLE));
95     // currently just for gc stw phase, so check it is not in allocating state
96     RegionIterateCheck iterate(this);
97     if (!IsTLAB()) {
98         auto cur_ptr = Begin();
99         auto end_ptr = Top();
100         while (cur_ptr < end_ptr) {
101             auto object_header = reinterpret_cast<ObjectHeader *>(cur_ptr);
102             size_t object_size = GetObjectSize(object_header);
103             visitor(object_header);
104             cur_ptr = AlignUp(cur_ptr + object_size, DEFAULT_ALIGNMENT_IN_BYTES);
105         }
106     } else {
107         for (auto i : *tlab_vector_) {
108             i->IterateOverObjects(visitor);
109         }
110     }
111 }
112 
113 template <typename RegionVisitor>
IterateRegions(RegionVisitor visitor)114 void RegionSpace::IterateRegions(RegionVisitor visitor)
115 {
116     auto it = regions_.begin();
117     while (it != regions_.end()) {
118         auto *region = Region::AsRegion(&(*it));
119         ++it;  // increase before visitor which may remove region
120         visitor(region);
121     }
122 }
123 
124 template <bool cross_region>
ContainObject(const ObjectHeader * object)125 bool RegionSpace::ContainObject(const ObjectHeader *object) const
126 {
127     return GetRegion<cross_region>(object) != nullptr;
128 }
129 
130 template <bool cross_region>
IsLive(const ObjectHeader * object)131 bool RegionSpace::IsLive(const ObjectHeader *object) const
132 {
133     auto *region = GetRegion<cross_region>(object);
134 
135     // check if the object is live in the range
136     return region != nullptr && region->IsInAllocRange(object);
137 }
138 
139 }  // namespace panda::mem
140 
141 #endif  // PANDA_RUNTIME_MEM_REGION_SPACE_INL_H
142