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#ifndef ECMASCRIPT_BASE_ATOMIC_HELPER_H
17#define ECMASCRIPT_BASE_ATOMIC_HELPER_H
18
19#include "ecmascript/js_dataview.h"
20
21namespace panda::ecmascript::base {
22enum class BytesSize : uint32_t {ONEBYTES = 1, TWOBYTES = 2, FOURBYTES = 4, EIGHTBYTES = 8};
23
24class AtomicHelper final {
25public:
26    struct SubFun {
27        template<typename T>
28        T operator()(T *ptr, const T *arg, [[maybe_unused]] uint32_t length) const
29        {
30            ASSERT(length >= 1); // 1: max argnum
31            std::atomic<T> *atomicValue = reinterpret_cast<std::atomic<T> *>(ptr);
32            return atomicValue->fetch_sub(arg[0], std::memory_order_seq_cst);
33        }
34    };
35
36    struct AddFun {
37        template<typename T>
38        T operator()(T *ptr, const T *arg, [[maybe_unused]] uint32_t length) const
39        {
40            ASSERT(length >= 1); // 1: max argnum
41            std::atomic<T> *atomicValue = reinterpret_cast<std::atomic<T> *>(ptr);
42            return atomicValue->fetch_add(arg[0], std::memory_order_seq_cst);
43        }
44    };
45
46    struct AndFun {
47        template<typename T>
48        T operator()(T *ptr, const T *arg, [[maybe_unused]] uint32_t length) const
49        {
50            ASSERT(length >= 1); // 1: max argnum
51            std::atomic<T> *atomicValue = reinterpret_cast<std::atomic<T> *>(ptr);
52            return atomicValue->fetch_and(arg[0], std::memory_order_seq_cst);
53        }
54    };
55
56    struct OrFun {
57        template<typename T>
58        T operator()(T *ptr, const T *arg, [[maybe_unused]] uint32_t length) const
59        {
60            ASSERT(length >= 1); // 1: max argnum
61            std::atomic<T> *atomicValue = reinterpret_cast<std::atomic<T> *>(ptr);
62            return atomicValue->fetch_or(arg[0], std::memory_order_seq_cst);
63        }
64    };
65
66    struct XorFun {
67        template<typename T>
68        T operator()(T *ptr, const T *arg, [[maybe_unused]] uint32_t length) const
69        {
70            ASSERT(length >= 1); // 1: max argnum
71            std::atomic<T> *atomicValue = reinterpret_cast<std::atomic<T> *>(ptr);
72            return atomicValue->fetch_xor(arg[0], std::memory_order_seq_cst);
73        }
74    };
75
76    struct CompareExchangeFun {
77        template<typename T>
78        T operator()(T *ptr, const T *arg, [[maybe_unused]] uint32_t length) const
79        {
80            ASSERT(length >= 2); // 2: max argnum
81            T a = arg[0];
82            std::atomic<T> *atomicValue = reinterpret_cast<std::atomic<T> *>(ptr);
83            atomicValue->compare_exchange_strong(a, arg[1], std::memory_order_seq_cst);
84            return a;
85        }
86    };
87
88    struct ExchangeFun {
89        template<typename T>
90        T operator()(T *ptr, const T *arg, [[maybe_unused]] uint32_t length) const
91        {
92            ASSERT(length >= 1); // 1: max argnum
93            std::atomic<T> *atomicValue = reinterpret_cast<std::atomic<T> *>(ptr);
94            return atomicValue->exchange(arg[0], std::memory_order_seq_cst);
95        }
96    };
97
98    // 25.4.1.1 ValidateIntegerTypedArray ( typedArray [ , waitable ] )
99    static JSTaggedValue ValidateIntegerTypedArray(JSThread *thread, JSHandle<JSTaggedValue> typedArray,
100                                                   bool waitable = false);
101    // 25.4.2.2 ValidateAtomicAccess ( typedArray, requestIndex )
102    static uint32_t ValidateAtomicAccess(JSThread *thread, const JSHandle<JSTaggedValue> typedArray,
103                                        JSHandle<JSTaggedValue> requestIndex);
104    static JSTaggedValue AtomicStore(JSThread *thread, const JSHandle<JSTaggedValue> &typedArray,
105                                     JSHandle<JSTaggedValue> index, JSHandle<JSTaggedValue> &value);
106    static JSTaggedValue AtomicLoad(JSThread *thread, const JSHandle<JSTaggedValue> &typedArray,
107                                    JSHandle<JSTaggedValue> index);
108};
109}  // namespace panda::ecmascript::base
110
111#endif  // ECMASCRIPT_BASE_ATOMIC_HELPER_H
112