• 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/marking_barrier.h"
16 
17 #include "common_components/mutator/mutator.h"
18 #if defined(COMMON_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* MarkingBarrier::ReadRefField(BaseObject* obj, RefField<false>& field) const
26 {
27     RefField<> tmpField(field);
28     return (BaseObject*)tmpField.GetFieldValue();
29 }
30 
ReadStaticRef(RefField<false> & field) const31 BaseObject* MarkingBarrier::ReadStaticRef(RefField<false>& field) const { return ReadRefField(nullptr, field); }
32 
ReadStruct(HeapAddress dst,BaseObject * obj,HeapAddress src,size_t size) const33 void MarkingBarrier::ReadStruct(HeapAddress dst, BaseObject* obj, HeapAddress src, size_t size) const
34 {
35     CHECK_CC(memcpy_s(reinterpret_cast<void*>(dst), size, reinterpret_cast<void*>(src), size) == EOK);
36 }
37 
WriteRoot(BaseObject * obj) const38 void MarkingBarrier::WriteRoot(BaseObject *obj) const
39 {
40     ASSERT(Heap::IsHeapAddress(obj));
41     Mutator *mutator = Mutator::GetMutator();
42     mutator->RememberObjectInSatbBuffer(obj);
43     DLOG(BARRIER, "write root obj %p", obj);
44 }
45 
WriteRefField(BaseObject * obj,RefField<false> & field,BaseObject * ref) const46 void MarkingBarrier::WriteRefField(BaseObject* obj, RefField<false>& field, BaseObject* ref) const
47 {
48     UpdateRememberSet(obj, ref);
49     RefField<> tmpField(field);
50     BaseObject* rememberedObject = nullptr;
51     rememberedObject = tmpField.GetTargetObject();
52     Mutator* mutator = Mutator::GetMutator();
53     if (rememberedObject != nullptr) {
54         mutator->RememberObjectInSatbBuffer(rememberedObject);
55     }
56     DLOG(BARRIER, "write obj %p ref-field@%p: %#zx -> %p", obj, &field, rememberedObject, ref);
57     std::atomic_thread_fence(std::memory_order_seq_cst);
58     RefField<> newField(ref);
59     field.SetFieldValue(newField.GetFieldValue());
60 }
61 #ifdef ARK_USE_SATB_BARRIER
WriteBarrier(BaseObject * obj,RefField<false> & field,BaseObject * ref) const62 void MarkingBarrier::WriteBarrier(BaseObject* obj, RefField<false>& field, BaseObject* ref) const
63 {
64     RefField<> tmpField(field);
65     BaseObject* rememberedObject = nullptr;
66     rememberedObject = tmpField.GetTargetObject();
67     if (!Heap::IsTaggedObject(field.GetFieldValue())) {
68         return;
69     }
70     UpdateRememberSet(obj, ref);
71     Mutator* mutator = Mutator::GetMutator();
72     if (rememberedObject != nullptr) {
73         mutator->RememberObjectInSatbBuffer(rememberedObject);
74     }
75     if (ref != nullptr) {
76         if (!Heap::IsTaggedObject((HeapAddress)ref)) {
77             return;
78         }
79         ref = (BaseObject*)((uintptr_t)ref & ~(TAG_WEAK));
80         mutator->RememberObjectInSatbBuffer(ref);
81     }
82 
83     DLOG(BARRIER, "write obj %p ref-field@%p: %#zx -> %p", obj, &field, rememberedObject, ref);
84 }
85 #else
WriteBarrier(BaseObject * obj,RefField<false> & field,BaseObject * ref) const86 void MarkingBarrier::WriteBarrier(BaseObject* obj, RefField<false>& field, BaseObject* ref) const
87 {
88     if (!Heap::IsTaggedObject((HeapAddress)ref)) {
89         return;
90     }
91     if (Heap::GetHeap().GetGCReason() == GC_REASON_YOUNG) {
92         UpdateRememberSet(obj, ref);
93     }
94     ref = (BaseObject*)((uintptr_t)ref & ~(TAG_WEAK));
95     Mutator* mutator = Mutator::GetMutator();
96     mutator->RememberObjectInSatbBuffer(ref);
97     DLOG(BARRIER, "write obj %p ref-field@%p: -> %p", obj, &field, ref);
98 }
99 #endif
100 
WriteStaticRef(RefField<false> & field,BaseObject * ref) const101 void MarkingBarrier::WriteStaticRef(RefField<false>& field, BaseObject* ref) const
102 {
103     std::atomic_thread_fence(std::memory_order_seq_cst);
104     RefField<> newField(ref);
105     field.SetFieldValue(newField.GetFieldValue());
106 }
107 
WriteStruct(BaseObject * obj,HeapAddress dst,size_t dstLen,HeapAddress src,size_t srcLen) const108 void MarkingBarrier::WriteStruct(BaseObject* obj, HeapAddress dst, size_t dstLen, HeapAddress src, size_t srcLen) const
109 {
110     CHECK_CC(obj != nullptr);
111     if (obj != nullptr) { //LCOV_EXCL_BR_LINE
112         ASSERT_LOGF(dst > reinterpret_cast<HeapAddress>(obj), "WriteStruct struct addr is less than obj!");
113         Mutator* mutator = Mutator::GetMutator();
114         if (mutator != nullptr) {
115             obj->ForEachRefInStruct(
116                 [=](RefField<>& refField) {
117                     mutator->RememberObjectInSatbBuffer(ReadRefField(obj, refField));
118                 },
119                 dst, dst + dstLen);
120         }
121     }
122     std::atomic_thread_fence(std::memory_order_seq_cst);
123     CHECK_CC(memcpy_s(reinterpret_cast<void*>(dst), dstLen, reinterpret_cast<void*>(src), srcLen) == EOK);
124 
125 #if defined(COMMON_TSAN_SUPPORT)
126     Sanitizer::TsanWriteMemoryRange(reinterpret_cast<void*>(dst), dstLen);
127     Sanitizer::TsanReadMemoryRange(reinterpret_cast<void*>(src), srcLen);
128 #endif
129 }
130 
AtomicReadRefField(BaseObject * obj,RefField<true> & field,MemoryOrder order) const131 BaseObject* MarkingBarrier::AtomicReadRefField(BaseObject* obj, RefField<true>& field, MemoryOrder order) const
132 {
133     BaseObject* target = nullptr;
134     RefField<false> oldField(field.GetFieldValue(order));
135     target = (BaseObject*)(oldField.GetFieldValue());
136     DLOG(TBARRIER, "katomic read obj %p ref@%p: %#zx -> %p", obj, &field, oldField.GetFieldValue(), target);
137     return target;
138 }
139 
AtomicWriteRefField(BaseObject * obj,RefField<true> & field,BaseObject * newRef,MemoryOrder order) const140 void MarkingBarrier::AtomicWriteRefField(BaseObject* obj, RefField<true>& field, BaseObject* newRef,
141                                          MemoryOrder order) const
142 {
143     RefField<> oldField(field.GetFieldValue(order));
144     HeapAddress oldValue = oldField.GetFieldValue();
145     (void)oldValue;
146     BaseObject* oldRef = oldField.GetTargetObject();
147     RefField<> newField(newRef);
148     field.SetFieldValue(newField.GetFieldValue(), order);
149     Mutator* mutator = Mutator::GetMutator();
150     mutator->RememberObjectInSatbBuffer(oldRef);
151     if (obj != nullptr) {
152         DLOG(TBARRIER, "atomic write obj %p<%p>(%zu) ref@%p: %#zx -> %#zx", obj, obj->GetTypeInfo(), obj->GetSize(),
153              &field, oldValue, newField.GetFieldValue());
154     } else {
155         DLOG(TBARRIER, "atomic write static ref@%p: %#zx -> %#zx", &field, oldValue, newField.GetFieldValue());
156     }
157 }
158 
AtomicSwapRefField(BaseObject * obj,RefField<true> & field,BaseObject * newRef,MemoryOrder order) const159 BaseObject* MarkingBarrier::AtomicSwapRefField(BaseObject* obj, RefField<true>& field, BaseObject* newRef,
160                                                MemoryOrder order) const
161 {
162     RefField<> newField(newRef);
163     HeapAddress oldValue = field.Exchange(newField.GetFieldValue(), order);
164     RefField<> oldField(oldValue);
165     BaseObject* oldRef = oldField.GetTargetObject();
166     Mutator* mutator = Mutator::GetMutator();
167     mutator->RememberObjectInSatbBuffer(oldRef);
168     DLOG(TRACE, "atomic swap obj %p<%p>(%zu) ref-field@%p: old %#zx(%p), new %#zx(%p)", obj, obj->GetTypeInfo(),
169          obj->GetSize(), &field, oldValue, oldRef, field.GetFieldValue(), newRef);
170     return oldRef;
171 }
172 
CompareAndSwapRefField(BaseObject * obj,RefField<true> & field,BaseObject * oldRef,BaseObject * newRef,MemoryOrder succOrder,MemoryOrder failOrder) const173 bool MarkingBarrier::CompareAndSwapRefField(BaseObject* obj, RefField<true>& field, BaseObject* oldRef,
174                                             BaseObject* newRef, MemoryOrder succOrder, MemoryOrder failOrder) const
175 {
176     HeapAddress oldFieldValue = field.GetFieldValue(std::memory_order_seq_cst);
177     RefField<false> oldField(oldFieldValue);
178     BaseObject* oldVersion = oldField.GetTargetObject();
179     RefField<> newField(newRef);
180 
181     while (oldVersion == oldRef) {
182         if (field.CompareExchange(oldFieldValue, newField.GetFieldValue(), succOrder, failOrder)) {
183             Mutator* mutator = Mutator::GetMutator();
184             mutator->RememberObjectInSatbBuffer(oldRef);
185             return true;
186         }
187         oldFieldValue = field.GetFieldValue(std::memory_order_seq_cst);
188         RefField<false> tmp(oldFieldValue);
189         oldVersion = tmp.GetTargetObject();
190     }
191 
192     return false;
193 }
194 
CopyStructArray(BaseObject * dstObj,HeapAddress dstField,MIndex dstSize,BaseObject * srcObj,HeapAddress srcField,MIndex srcSize) const195 void MarkingBarrier::CopyStructArray(BaseObject* dstObj, HeapAddress dstField, MIndex dstSize, BaseObject* srcObj,
196                                      HeapAddress srcField, MIndex srcSize) const
197 {
198     LOG_COMMON(FATAL) << "Unresolved fatal";
199     UNREACHABLE_CC();
200 }
201 
202 } // namespace common
203