1/*
2 * Copyright (c) 2021 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#ifndef ECMASCRIPT_MEM_BARRIERS_H
17#define ECMASCRIPT_MEM_BARRIERS_H
18
19#include "ecmascript/common.h"
20#include "ecmascript/js_tagged_value.h"
21#include "ecmascript/mem/mark_word.h"
22#include "ecmascript/mem/mem_common.h"
23
24namespace panda::ecmascript {
25class Region;
26
27enum class WriteBarrierType : size_t { NORMAL, DESERIALIZE };
28
29class Barriers {
30public:
31    template<class T>
32    static inline void SetPrimitive(void *obj, size_t offset, T value)
33    {
34        auto *addr = reinterpret_cast<T *>(ToUintPtr(obj) + offset);
35        // NOLINTNEXTLINE(clang-analyzer-core.NullDereference)
36        *addr = value;
37    }
38
39    template<class T>
40    static inline T AtomicSetPrimitive(volatile void *obj, size_t offset, T oldValue, T value)
41    {
42        volatile auto atomicField = reinterpret_cast<volatile std::atomic<T> *>(ToUintPtr(obj) + offset);
43        std::atomic_compare_exchange_strong_explicit(atomicField, &oldValue, value, std::memory_order_release,
44                                                     std::memory_order_relaxed);
45        return oldValue;
46    }
47
48    template<bool needWriteBarrier = true>
49    static void SetObject(const JSThread *thread, void *obj, size_t offset, JSTaggedType value);
50
51    template<bool needWriteBarrier, bool maybeOverlap>
52    static void CopyObject(const JSThread *thread, JSTaggedValue* dst, JSTaggedValue* src, size_t count);
53
54    template<bool maybeOverlap>
55    static void CopyObjectPrimitive(JSTaggedValue* dst, JSTaggedValue* src, size_t count);
56    static void SynchronizedSetClass(const JSThread *thread, void *obj, JSTaggedType value);
57    static void SynchronizedSetObject(const JSThread *thread, void *obj, size_t offset, JSTaggedType value,
58                                      bool isPrimitive = false);
59
60    template<class T>
61    static inline T GetValue(const void *obj, size_t offset)
62    {
63        auto *addr = reinterpret_cast<T *>(ToUintPtr(obj) + offset);
64        return *addr;
65    }
66
67    static void PUBLIC_API Update(const JSThread *thread, uintptr_t slotAddr, Region *objectRegion,
68                                  TaggedObject *value, Region *valueRegion,
69                                  WriteBarrierType writeType = WriteBarrierType::NORMAL);
70    static void PUBLIC_API UpdateWithoutEden(const JSThread *thread, uintptr_t slotAddr, Region *objectRegion,
71                                             TaggedObject *value, Region *valueRegion,
72                                             WriteBarrierType writeType = WriteBarrierType::NORMAL);
73
74    static void PUBLIC_API UpdateShared(const JSThread *thread, TaggedObject *value, Region *valueRegion);
75};
76}  // namespace panda::ecmascript
77
78#endif  // ECMASCRIPT_MEM_BARRIERS_H
79