• 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/idle_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 #include "securec.h"
22 
23 namespace common {
ReadRefField(BaseObject * obj,RefField<false> & field) const24 BaseObject* IdleBarrier::ReadRefField(BaseObject* obj, RefField<false>& field) const
25 {
26     RefField<> oldField(field);
27     return (BaseObject*)(oldField.GetFieldValue());
28 }
29 
ReadStaticRef(RefField<false> & field) const30 BaseObject* IdleBarrier::ReadStaticRef(RefField<false>& field) const { return ReadRefField(nullptr, field); }
31 
AtomicReadRefField(BaseObject * obj,RefField<true> & field,MemoryOrder order) const32 BaseObject* IdleBarrier::AtomicReadRefField(BaseObject* obj, RefField<true>& field, MemoryOrder order) const
33 {
34     RefField<false> oldField(field.GetFieldValue(order));
35     BaseObject* target = (BaseObject*)(oldField.GetFieldValue());
36     DLOG(BARRIER, "atomic read obj %p ref@%p: %#zx -> %p", obj, &field, oldField.GetFieldValue(), target);
37     return target;
38 }
39 
ReadStruct(HeapAddress dst,BaseObject * obj,HeapAddress src,size_t size) const40 void IdleBarrier::ReadStruct(HeapAddress dst, BaseObject* obj, HeapAddress src, size_t size) const
41 {
42     LOGF_CHECK(memcpy_s(reinterpret_cast<void*>(dst), size, reinterpret_cast<void*>(src), size) == EOK) <<
43         "read struct memcpy_s failed";
44 }
45 
AtomicWriteRefField(BaseObject * obj,RefField<true> & field,BaseObject * newRef,MemoryOrder order) const46 void IdleBarrier::AtomicWriteRefField(BaseObject* obj, RefField<true>& field, BaseObject* newRef,
47                                       MemoryOrder order) const
48 {
49     if (obj != nullptr) {
50         DLOG(BARRIER, "atomic write obj %p<%p>(%zu) ref@%p: %p", obj, obj->GetTypeInfo(), obj->GetSize(), &field,
51              newRef);
52     } else {
53         DLOG(BARRIER, "atomic write static ref@%p: %p", &field, newRef);
54     }
55     field.SetTargetObject(newRef, order);
56 }
57 
AtomicSwapRefField(BaseObject * obj,RefField<true> & field,BaseObject * newRef,MemoryOrder order) const58 BaseObject* IdleBarrier::AtomicSwapRefField(BaseObject* obj, RefField<true>& field, BaseObject* newRef,
59                                             MemoryOrder order) const
60 {
61     // newRef must be the latest versions.
62     HeapAddress oldValue = field.Exchange(newRef, order);
63     RefField<> oldField(oldValue);
64     BaseObject* oldRef = ReadRefField(nullptr, oldField);
65     DLOG(BARRIER, "atomic swap obj %p<%p>(%zu) ref@%p: old %#zx(%p), new %#zx(%p)", obj, obj->GetTypeInfo(),
66          obj->GetSize(), &field, oldValue, oldRef, field.GetFieldValue(order), newRef);
67     return oldRef;
68 }
69 
CompareAndSwapRefField(BaseObject * obj,RefField<true> & field,BaseObject * oldRef,BaseObject * newRef,MemoryOrder sOrder,MemoryOrder fOrder) const70 bool IdleBarrier::CompareAndSwapRefField(BaseObject* obj, RefField<true>& field, BaseObject* oldRef,
71                                          BaseObject* newRef, MemoryOrder sOrder, MemoryOrder fOrder) const
72 {
73     HeapAddress oldFieldValue = field.GetFieldValue(std::memory_order_seq_cst);
74     RefField<false> oldField(oldFieldValue);
75     BaseObject* oldVersion = ReadRefField(nullptr, oldField);
76 
77     // oldRef and newRef must be the latest versions.
78     while (oldVersion == oldRef) {
79         RefField<> newField(newRef);
80         if (field.CompareExchange(oldFieldValue, newField.GetFieldValue(), sOrder, fOrder)) {
81             return true;
82         }
83         oldFieldValue = field.GetFieldValue(std::memory_order_seq_cst);
84         RefField<false> tmp(oldFieldValue);
85         oldVersion = ReadRefField(nullptr, tmp);
86     }
87     return false;
88 }
89 
UpdateRememberSet(BaseObject * object,BaseObject * ref) const90 void IdleBarrier::UpdateRememberSet(BaseObject* object, BaseObject* ref) const
91 {
92     ASSERT(object != nullptr);
93     RegionDesc::InlinedRegionMetaData *objMetaRegion = RegionDesc::InlinedRegionMetaData::GetInlinedRegionMetaData(
94         reinterpret_cast<uintptr_t>(object));
95     RegionDesc::InlinedRegionMetaData *refMetaRegion = RegionDesc::InlinedRegionMetaData::GetInlinedRegionMetaData(
96         reinterpret_cast<uintptr_t>(ref));
97     if (!objMetaRegion->IsInYoungSpaceForWB() && refMetaRegion->IsInYoungSpaceForWB()) {
98         if (objMetaRegion->MarkRSetCardTable(object)) {
99             DLOG(BARRIER, "update point-out remember set of region %p, obj %p, ref: %p<%p>",
100                  objMetaRegion->GetRegionDesc(), object, ref, ref->GetTypeInfo());
101         }
102     }
103 }
104 
WriteRoot(BaseObject * obj) const105 void IdleBarrier::WriteRoot(BaseObject *obj) const
106 {
107     DLOG(BARRIER, "write root obj %p", obj);
108 }
109 
WriteRefField(BaseObject * obj,RefField<false> & field,BaseObject * ref) const110 void IdleBarrier::WriteRefField(BaseObject* obj, RefField<false>& field, BaseObject* ref) const
111 {
112     DLOG(BARRIER, "write obj %p ref@%p: %p => %p", obj, &field, field.GetTargetObject(), ref);
113     if (Heap::IsTaggedObject((HeapAddress)ref)) {
114         UpdateRememberSet(obj, ref);
115     }
116     field.SetTargetObject(ref);
117 }
118 
WriteBarrier(BaseObject * obj,RefField<false> & field,BaseObject * ref) const119 void IdleBarrier::WriteBarrier(BaseObject* obj, RefField<false>& field, BaseObject* ref) const
120 {
121     if (!Heap::IsTaggedObject((HeapAddress)ref)) {
122         return;
123     }
124     UpdateRememberSet(obj, ref);
125     DLOG(BARRIER, "write obj %p ref@%p: %p => %p", obj, &field, field.GetTargetObject(), ref);
126 }
127 
WriteStruct(BaseObject * obj,HeapAddress dst,size_t dstLen,HeapAddress src,size_t srcLen) const128 void IdleBarrier::WriteStruct(BaseObject* obj, HeapAddress dst, size_t dstLen, HeapAddress src, size_t srcLen) const
129 {
130     CHECK_CC(memcpy_s(reinterpret_cast<void*>(dst), dstLen, reinterpret_cast<void*>(src), srcLen) == EOK);
131 #if defined(COMMON_TSAN_SUPPORT)
132     CHECK_CC(srcLen == dstLen);
133     Sanitizer::TsanWriteMemoryRange(reinterpret_cast<void*>(dst), dstLen);
134     Sanitizer::TsanReadMemoryRange(reinterpret_cast<void*>(src), srcLen);
135 #endif
136 }
137 
WriteStaticRef(RefField<false> & field,BaseObject * ref) const138 void IdleBarrier::WriteStaticRef(RefField<false>& field, BaseObject* ref) const { WriteRefField(nullptr, field, ref); }
139 
CopyStructArray(BaseObject * dstObj,HeapAddress dstField,MIndex dstSize,BaseObject * srcObj,HeapAddress srcField,MIndex srcSize) const140 void IdleBarrier::CopyStructArray(BaseObject* dstObj, HeapAddress dstField, MIndex dstSize, BaseObject* srcObj,
141                                   HeapAddress srcField, MIndex srcSize) const
142 {
143 #ifndef NDEBUG
144     if (!dstObj->HasRefField()) {
145         LOG_COMMON(FATAL) << "array " << dstObj << " doesn't have class-type element";
146         return;
147     }
148 #endif
149 
150     LOGF_CHECK(memmove_s(reinterpret_cast<void*>(dstField), dstSize, reinterpret_cast<void*>(srcField), srcSize) ==
151         EOK) << "memmove_s failed";
152 
153 #if defined(COMMON_TSAN_SUPPORT)
154     Sanitizer::TsanWriteMemoryRange(reinterpret_cast<void*>(dstField), dstSize);
155     Sanitizer::TsanReadMemoryRange(reinterpret_cast<void*>(srcField), srcSize);
156 #endif
157 }
158 } // namespace common
159