1 /*
2 * Copyright (c) 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
16 #include "ecmascript/mem/work_manager-inl.h"
17 #include "ecmascript/runtime.h"
18
19 namespace panda::ecmascript {
Update(const JSThread * thread,uintptr_t slotAddr,Region * objectRegion,TaggedObject * value,Region * valueRegion,WriteBarrierType writeType)20 void Barriers::Update(const JSThread *thread, uintptr_t slotAddr, Region *objectRegion, TaggedObject *value,
21 Region *valueRegion, WriteBarrierType writeType)
22 {
23 if (valueRegion->InSharedHeap()) {
24 return;
25 }
26 auto heap = thread->GetEcmaVM()->GetHeap();
27 if (heap->IsConcurrentFullMark()) {
28 if (valueRegion->InCollectSet() && !objectRegion->InYoungSpaceOrCSet()) {
29 objectRegion->AtomicInsertCrossRegionRSet(slotAddr);
30 }
31 } else {
32 if (!valueRegion->InYoungSpace()) {
33 return;
34 }
35 }
36
37 // Weak ref record and concurrent mark record maybe conflict.
38 // This conflict is solved by keeping alive weak reference. A small amount of floating garbage may be added.
39 TaggedObject *heapValue = JSTaggedValue(value).GetHeapObject();
40 if (valueRegion->IsFreshRegion()) {
41 valueRegion->NonAtomicMark(heapValue);
42 } else if (writeType != WriteBarrierType::DESERIALIZE && valueRegion->AtomicMark(heapValue)) {
43 heap->GetWorkManager()->GetWorkNodeHolder(MAIN_THREAD_INDEX)->Push(heapValue);
44 }
45 }
46
UpdateShared(const JSThread * thread,uintptr_t slotAddr,Region * objectRegion,TaggedObject * value,Region * valueRegion)47 void Barriers::UpdateShared(const JSThread *thread, uintptr_t slotAddr, Region *objectRegion, TaggedObject *value,
48 Region *valueRegion)
49 {
50 ASSERT(DaemonThread::GetInstance()->IsConcurrentMarkingOrFinished());
51 ASSERT(valueRegion->InSharedSweepableSpace());
52 if (valueRegion->InSCollectSet() && objectRegion->InSharedHeap()) {
53 objectRegion->AtomicInsertCrossRegionRSet(slotAddr);
54 }
55 // Weak ref record and concurrent mark record maybe conflict.
56 // This conflict is solved by keeping alive weak reference. A small amount of floating garbage may be added.
57 TaggedObject *heapValue = JSTaggedValue(value).GetHeapObject();
58 if (valueRegion->AtomicMark(heapValue)) {
59 Heap *heap = const_cast<Heap*>(thread->GetEcmaVM()->GetHeap());
60 WorkNode *&localBuffer = heap->GetMarkingObjectLocalBuffer();
61 SharedHeap::GetInstance()->GetWorkManager()->PushToLocalMarkingBuffer(localBuffer, heapValue);
62 }
63 }
64
65
66 template <Region::RegionSpaceKind kind>
BatchBitSet(const JSThread * thread,Region * objectRegion,JSTaggedValue * dst,size_t count)67 ARK_NOINLINE bool BatchBitSet([[maybe_unused]] const JSThread* thread, Region* objectRegion, JSTaggedValue* dst,
68 size_t count)
69 {
70 bool allValueNotHeap = true;
71 Region::Updater updater = objectRegion->GetBatchRSetUpdater<kind>(ToUintPtr(dst));
72 for (size_t i = 0; i < count; i++, updater.Next()) {
73 JSTaggedValue taggedValue = dst[i];
74 if (!taggedValue.IsHeapObject()) {
75 continue;
76 }
77 allValueNotHeap = false;
78 const Region* valueRegion = Region::ObjectAddressToRange(taggedValue.GetTaggedObject());
79 #if ECMASCRIPT_ENABLE_BARRIER_CHECK
80 ASSERT(taggedValue.GetRawData() != JSTaggedValue::VALUE_UNDEFINED);
81 if (!thread->GetEcmaVM()->GetHeap()->IsAlive(taggedValue.GetHeapObject())) {
82 LOG_FULL(FATAL) << "WriteBarrier checked value:" << taggedValue.GetRawData() << " is invalid!";
83 }
84 #endif
85 if (valueRegion->InSharedSweepableSpace()) {
86 #ifndef NDEBUG
87 if (UNLIKELY(taggedValue.IsWeakForHeapObject())) {
88 CHECK_NO_LOCAL_TO_SHARE_WEAK_REF_HANDLE;
89 }
90 #endif
91 updater.UpdateLocalToShare();
92 continue;
93 }
94 if constexpr (kind == Region::InGeneralOld) {
95 if (valueRegion->InYoungSpace()) {
96 updater.UpdateOldToNew();
97 continue;
98 }
99 }
100 }
101 return allValueNotHeap;
102 }
103
104 template bool BatchBitSet<Region::InYoung>(const JSThread*, Region*, JSTaggedValue*, size_t);
105 template bool BatchBitSet<Region::InGeneralOld>(const JSThread*, Region*, JSTaggedValue*, size_t);
106 template bool BatchBitSet<Region::Other>(const JSThread*, Region*, JSTaggedValue*, size_t);
107
108 } // namespace panda::ecmascript
109