• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 #include "common_components/heap/ark_collector/remark_barrier.h"
16 #include "common_components/heap/allocator/region_space.h"
17 #include "common_components/mutator/mutator.h"
18 #if defined(ARKCOMMON_TSAN_SUPPORT)
19 #include "common_components/sanitizer/sanitizer_interface.h"
20 #endif
21 
22 namespace common {
23 // Because gc thread will also have impact on tagged pointer in enum and marking phase,
24 // so we don't expect reading barrier have the ability to modify the referent field.
ReadRefField(BaseObject * obj,RefField<false> & field) const25 BaseObject* RemarkBarrier::ReadRefField(BaseObject* obj, RefField<false>& field) const
26 {
27     RefField<> tmpField(field);
28     return reinterpret_cast<BaseObject*>(tmpField.GetFieldValue());
29 }
30 
ReadStaticRef(RefField<false> & field) const31 BaseObject* RemarkBarrier::ReadStaticRef(RefField<false>& field) const { return ReadRefField(nullptr, field); }
32 
33 
34 // If the object is still alive, return it; if not, return nullptr
ReadStringTableStaticRef(RefField<false> & field) const35 BaseObject* RemarkBarrier::ReadStringTableStaticRef(RefField<false> &field) const
36 {
37     // Note: CMC GC assumes all objects in string table are not in young space. Based on the assumption, CMC GC skip
38     // read barrier in young GC
39     if (Heap::GetHeap().GetGCReason() == GC_REASON_YOUNG) {
40         return reinterpret_cast<BaseObject*>(field.GetFieldValue());
41     }
42 
43     auto isSurvivor = [](BaseObject* obj) {
44         RegionDesc* region = RegionDesc::GetAliveRegionDescAt(reinterpret_cast<HeapAddress>(obj));
45 
46         return region->IsMarkedObject(obj) || region->IsNewObjectSinceMarking(obj);
47     };
48 
49     auto obj = ReadRefField(nullptr, field);
50     if (obj != nullptr && isSurvivor(obj)) {
51         return obj;
52     } else {
53         return nullptr;
54     }
55 }
56 
ReadStruct(HeapAddress dst,BaseObject * obj,HeapAddress src,size_t size) const57 void RemarkBarrier::ReadStruct(HeapAddress dst, BaseObject *obj, HeapAddress src, size_t size) const
58 {
59     CHECK_CC(memcpy_s(reinterpret_cast<void *>(dst), size, reinterpret_cast<void *>(src), size) == EOK);
60 }
61 
WriteRoot(BaseObject * obj) const62 void RemarkBarrier::WriteRoot(BaseObject *obj) const
63 {
64     ASSERT(Heap::IsHeapAddress(obj));
65     Mutator *mutator = Mutator::GetMutator();
66     mutator->RememberObjectInSatbBuffer(obj);
67     DLOG(BARRIER, "write root obj %p", obj);
68 }
69 
WriteRefField(BaseObject * obj,RefField<false> & field,BaseObject * ref) const70 void RemarkBarrier::WriteRefField(BaseObject *obj, RefField<false> &field, BaseObject *ref) const
71 {
72     UpdateRememberSet(obj, ref);
73     RefField<> tmpField(field);
74     BaseObject *rememberedObject = nullptr;
75     rememberedObject = tmpField.GetTargetObject();
76     Mutator *mutator = Mutator::GetMutator();
77     if (rememberedObject != nullptr) {
78         mutator->RememberObjectInSatbBuffer(rememberedObject);
79     }
80     DLOG(BARRIER, "write obj %p ref-field@%p: %#zx -> %p", obj, &field,
81         rememberedObject, ref);
82     std::atomic_thread_fence(std::memory_order_seq_cst);
83     RefField<> newField(ref);
84     field.SetFieldValue(newField.GetFieldValue());
85 }
86 #ifdef ARK_USE_SATB_BARRIER
WriteBarrier(BaseObject * obj,RefField<false> & field,BaseObject * ref) const87 void RemarkBarrier::WriteBarrier(BaseObject* obj, RefField<false>& field, BaseObject* ref) const
88 {
89     RefField<> tmpField(field);
90     BaseObject* rememberedObject = nullptr;
91     rememberedObject = tmpField.GetTargetObject();
92     if (!Heap::IsTaggedObject(field.GetFieldValue())) {
93         return;
94     }
95     UpdateRememberSet(obj, ref);
96     Mutator* mutator = Mutator::GetMutator();
97     if (rememberedObject != nullptr) {
98         mutator->RememberObjectInSatbBuffer(rememberedObject);
99     }
100     if (ref != nullptr) {
101         if (!Heap::IsTaggedObject((HeapAddress)ref)) {
102             return;
103         }
104         ref = reinterpret_cast<BaseObject*>(reinterpret_cast<uintptr_t>(ref) & ~TAG_WEAK);
105         mutator->RememberObjectInSatbBuffer(ref);
106     }
107 
108     DLOG(BARRIER, "write obj %p ref-field@%p: %#zx -> %p", obj, &field, rememberedObject, ref);
109 }
110 #else
WriteBarrier(BaseObject * obj,RefField<false> & field,BaseObject * ref) const111 void RemarkBarrier::WriteBarrier(BaseObject* obj, RefField<false>& field, BaseObject* ref) const
112 {
113     if (!Heap::IsTaggedObject((HeapAddress)ref)) {
114         return;
115     }
116     UpdateRememberSet(obj, ref);
117     ref = reinterpret_cast<BaseObject*>(reinterpret_cast<uintptr_t>(ref) & ~TAG_WEAK);
118     Mutator* mutator = Mutator::GetMutator();
119     mutator->RememberObjectInSatbBuffer(ref);
120     DLOG(BARRIER, "write obj %p ref-field@%p: -> %p", obj, &field, ref);
121 }
122 #endif
123 
WriteStaticRef(RefField<false> & field,BaseObject * ref) const124 void RemarkBarrier::WriteStaticRef(RefField<false>& field, BaseObject* ref) const
125 {
126     std::atomic_thread_fence(std::memory_order_seq_cst);
127     RefField<> newField(ref);
128     field.SetFieldValue(newField.GetFieldValue());
129 }
130 
WriteStruct(BaseObject * obj,HeapAddress dst,size_t dstLen,HeapAddress src,size_t srcLen) const131 void RemarkBarrier::WriteStruct(BaseObject* obj, HeapAddress dst, size_t dstLen, HeapAddress src, size_t srcLen) const
132 {
133     CHECK_CC(obj != nullptr);
134     if (obj != nullptr) { //LCOV_EXCL_BR_LINE
135         ASSERT_LOGF(dst > reinterpret_cast<HeapAddress>(obj), "WriteStruct struct addr is less than obj!");
136         Mutator* mutator = Mutator::GetMutator();
137         if (mutator != nullptr) {
138             obj->ForEachRefInStruct(
139                 [=](RefField<>& refField) {
140                     mutator->RememberObjectInSatbBuffer(ReadRefField(obj, refField));
141                 },
142                 dst, dst + dstLen);
143         }
144     }
145     std::atomic_thread_fence(std::memory_order_seq_cst);
146     CHECK_CC(memcpy_s(reinterpret_cast<void*>(dst), dstLen, reinterpret_cast<void*>(src), srcLen) == EOK);
147 
148 #if defined(ARKCOMMON_TSAN_SUPPORT)
149     Sanitizer::TsanWriteMemoryRange(reinterpret_cast<void*>(dst), dstLen);
150     Sanitizer::TsanReadMemoryRange(reinterpret_cast<void*>(src), srcLen);
151 #endif
152 }
153 
AtomicReadRefField(BaseObject * obj,RefField<true> & field,MemoryOrder order) const154 BaseObject* RemarkBarrier::AtomicReadRefField(BaseObject* obj, RefField<true>& field, MemoryOrder order) const
155 {
156     BaseObject* target = nullptr;
157     RefField<false> oldField(field.GetFieldValue(order));
158     target =  reinterpret_cast<BaseObject*>((oldField.GetFieldValue()));
159     DLOG(TBARRIER, "katomic read obj %p ref@%p: %#zx -> %p", obj, &field, oldField.GetFieldValue(), target);
160     return target;
161 }
162 
AtomicWriteRefField(BaseObject * obj,RefField<true> & field,BaseObject * newRef,MemoryOrder order) const163 void RemarkBarrier::AtomicWriteRefField(BaseObject *obj, RefField<true> &field,
164                                         BaseObject *newRef,
165                                         MemoryOrder order) const
166 {
167     RefField<> oldField(field.GetFieldValue(order));
168     HeapAddress oldValue = oldField.GetFieldValue();
169     BaseObject* oldRef = oldField.GetTargetObject();
170     RefField<> newField(newRef);
171     field.SetFieldValue(newField.GetFieldValue(), order);
172     Mutator* mutator = Mutator::GetMutator();
173     mutator->RememberObjectInSatbBuffer(oldRef);
174     if (obj != nullptr) {
175         DLOG(TBARRIER, "atomic write obj %p<%p>(%zu) ref@%p: %#zx -> %#zx", obj, obj->GetTypeInfo(), obj->GetSize(),
176              &field, oldValue, newField.GetFieldValue());
177     } else {
178         DLOG(TBARRIER, "atomic write static ref@%p: %#zx -> %#zx", &field, oldValue, newField.GetFieldValue());
179     }
180 }
181 
AtomicSwapRefField(BaseObject * obj,RefField<true> & field,BaseObject * newRef,MemoryOrder order) const182 BaseObject *RemarkBarrier::AtomicSwapRefField(BaseObject *obj,
183                                               RefField<true> &field,
184                                               BaseObject *newRef,
185                                               MemoryOrder order) const
186 {
187     RefField<> newField(newRef);
188     HeapAddress oldValue = field.Exchange(newField.GetFieldValue(), order);
189     RefField<> oldField(oldValue);
190     BaseObject* oldRef = oldField.GetTargetObject();
191     Mutator* mutator = Mutator::GetMutator();
192     mutator->RememberObjectInSatbBuffer(oldRef);
193     DLOG(TRACE, "atomic swap obj %p<%p>(%zu) ref-field@%p: old %#zx(%p), new %#zx(%p)", obj, obj->GetTypeInfo(),
194          obj->GetSize(), &field, oldValue, oldRef, field.GetFieldValue(), newRef);
195     return oldRef;
196 }
197 
CompareAndSwapRefField(BaseObject * obj,RefField<true> & field,BaseObject * oldRef,BaseObject * newRef,MemoryOrder succOrder,MemoryOrder failOrder) const198 bool RemarkBarrier::CompareAndSwapRefField(
199     BaseObject *obj, RefField<true> &field, BaseObject *oldRef,
200     BaseObject *newRef, MemoryOrder succOrder, MemoryOrder failOrder) const
201 {
202     HeapAddress oldFieldValue = field.GetFieldValue(std::memory_order_seq_cst);
203     RefField<false> oldField(oldFieldValue);
204     BaseObject* oldVersion = oldField.GetTargetObject();
205     RefField<> newField(newRef);
206 
207     while (oldVersion == oldRef) {
208         if (field.CompareExchange(oldFieldValue, newField.GetFieldValue(), succOrder, failOrder)) {
209             Mutator* mutator = Mutator::GetMutator();
210             mutator->RememberObjectInSatbBuffer(oldRef);
211             return true;
212         }
213         oldFieldValue = field.GetFieldValue(std::memory_order_seq_cst);
214         RefField<false> tmp(oldFieldValue);
215         oldVersion = tmp.GetTargetObject();
216     }
217 
218     return false;
219 }
220 
CopyStructArray(BaseObject * dstObj,HeapAddress dstField,MIndex dstSize,BaseObject * srcObj,HeapAddress srcField,MIndex srcSize) const221 void RemarkBarrier::CopyStructArray(BaseObject *dstObj, HeapAddress dstField,
222                                     MIndex dstSize, BaseObject *srcObj,
223                                     HeapAddress srcField,
224                                     MIndex srcSize) const
225 {
226     LOG_COMMON(FATAL) << "Unresolved fatal";
227 }
228 
229 } // namespace panda
230 
231