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_BUILTINS_BUILTINS_ATOMICS_H
17#define ECMASCRIPT_BUILTINS_BUILTINS_ATOMICS_H
18
19#include "ecmascript/base/builtins_base.h"
20#include "ecmascript/js_dataview.h"
21#include "ecmascript/waiter_list.h"
22
23// List of functions in Atomics.
24// V(name, func, length, stubIndex)
25// where BuiltinsAtomics::func refers to the native implementation of Atomics[name].
26//       kungfu::BuiltinsStubCSigns::stubIndex refers to the builtin stub index, or INVALID if no stub available.
27// The following functions are not implemented yet:
28//   - Atomics.waitAsync ( typedArray, index, value, timeout )
29#define BUILTIN_ATOMICS_FUNCTIONS(V)                                                         \
30    /* Atomics.add ( typedArray, index, value ) */                                          \
31    V("add", Add, 3, INVALID)                                                               \
32    /* Atomics.and ( typedArray, index, value ) */                                          \
33    V("and", And, 3, INVALID)                                                               \
34    /* Atomics.compareExchange ( typedArray, index, expectedValue, replacementValue ) */    \
35    V("compareExchange", CompareExchange, 4, INVALID)                                       \
36    /* Atomics.exchange ( typedArray, index, value ) */                                     \
37    V("exchange", Exchange, 3, INVALID)                                                     \
38    /* Atomics.isLockFree ( size ) */                                                       \
39    V("isLockFree", IsLockFree, 1, INVALID)                                                 \
40    /* Atomics.load ( typedArray, index ) */                                                \
41    V("load", Load, 2, INVALID)                                                             \
42    /* Atomics.notify ( typedArray, index, count ) */                                       \
43    V("notify", Notify, 3, INVALID)                                                         \
44    /* Atomics.or ( typedArray, index, value ) */                                           \
45    V("or", Or, 3, INVALID)                                                                 \
46    /* Atomics.store ( typedArray, index, value ) */                                        \
47    V("store", Store, 3, INVALID)                                                           \
48    /* Atomics.sub ( typedArray, index, value ) */                                          \
49    V("sub", Sub, 3, INVALID)                                                               \
50    /* Atomics.wait ( typedArray, index, value, timeout ) */                                \
51    V("wait", Wait, 4, INVALID)                                                             \
52    /* Atomics.xor ( typedArray, index, value ) */                                          \
53    V("xor", Xor, 3, INVALID)
54
55namespace panda::ecmascript::builtins {
56enum class WaitResult: uint8_t {OK = 0, NOT_EQ, TIME_OUT};
57
58class BuiltinsAtomics : public base::BuiltinsBase {
59public:
60    // 25.4.2 Atomics.add ( typedArray, index, value )
61    static JSTaggedValue Add(EcmaRuntimeCallInfo *argv);
62    // 25.4.3 Atomics.and ( typedArray, index, value )
63    static JSTaggedValue And(EcmaRuntimeCallInfo *argv);
64    // 25.4.4 Atomics.compareExchange ( typedArray, index, expectedValue, replacementValue)
65    static JSTaggedValue CompareExchange(EcmaRuntimeCallInfo *argv);
66    // 25.4.5 Atomics.exchange ( typedArray, index, value )
67    static JSTaggedValue Exchange(EcmaRuntimeCallInfo *argv);
68    // 25.4.6 Atomics.isLockFree ( size )
69    static JSTaggedValue IsLockFree(EcmaRuntimeCallInfo *argv);
70    // 25.4.7 Atomics.load ( typedArray, index )
71    static JSTaggedValue Load(EcmaRuntimeCallInfo *argv);
72	 // 25.4.8 Atomics.or ( typedArray, index, value )
73    static JSTaggedValue Or(EcmaRuntimeCallInfo *argv);
74    // 25.4.9 Atomics.store ( typedArray, index, value )
75    static JSTaggedValue Store(EcmaRuntimeCallInfo *argv);
76    // 25.4.10 Atomics.sub ( typedArray, index, value )
77    static JSTaggedValue Sub(EcmaRuntimeCallInfo *argv);
78    // 25.4.11 Atomics.wait ( typedArray, index, value, timeout)
79    static JSTaggedValue Wait(EcmaRuntimeCallInfo *argv);
80    // 25.4.12 Atomics.notify ( typedArray, index, count)
81    static JSTaggedValue Notify(EcmaRuntimeCallInfo *argv);
82    // 25.4.13 Atomics.xor ( typedArray, index, value )
83    static JSTaggedValue Xor(EcmaRuntimeCallInfo *argv);
84
85    static Span<const base::BuiltinFunctionEntry> GetAtomicsFunctions()
86    {
87        return Span<const base::BuiltinFunctionEntry>(ATOMICS_FUNCTIONS);
88    }
89
90private:
91#define BUILTINS_ATOMICS_FUNCTION_ENTRY(name, method, length, id) \
92    base::BuiltinFunctionEntry::Create(name, BuiltinsAtomics::method, length, kungfu::BuiltinsStubCSigns::id),
93
94    static constexpr std::array ATOMICS_FUNCTIONS  = {
95        BUILTIN_ATOMICS_FUNCTIONS(BUILTINS_ATOMICS_FUNCTION_ENTRY)
96    };
97#undef BUILTINS_ATOMICS_FUNCTION_ENTRY
98
99    static uint32_t Signal(JSHandle<JSTaggedValue> &arrayBuffer, const size_t &index, double wakeCount);
100    template <typename T>
101    static WaitResult DoWait(JSThread *thread, JSHandle<JSTaggedValue> &arrayBuffer,
102                             size_t index, T execpt, double timeout);
103    template<typename callbackfun>
104    static JSTaggedValue AtomicReadModifyWrite(JSThread *thread, const JSHandle<JSTaggedValue> &typedArray,
105                                               JSHandle<JSTaggedValue> &index, EcmaRuntimeCallInfo *argv,
106                                               const callbackfun &op);
107    template<typename callbackfun>
108    static JSTaggedValue AtomicReadModifyWriteCase(JSThread *thread, JSTaggedValue buffer, DataViewType type,
109                                                   uint32_t indexedPosition, EcmaRuntimeCallInfo *argv,
110                                                   const callbackfun &op);
111    template<typename callbackfun>
112    static JSTaggedValue HandleWithUint8(JSThread *thread, uint32_t size, uint8_t *block, uint32_t indexedPosition,
113                                         EcmaRuntimeCallInfo *argv, const callbackfun &op, uint8_t &tag);
114    template<typename callbackfun>
115    static JSTaggedValue HandleWithInt8(JSThread *thread, uint32_t size, uint8_t *block, uint32_t indexedPosition,
116                                        EcmaRuntimeCallInfo *argv, const callbackfun &op, int8_t &tag);
117    template<typename callbackfun>
118    static JSTaggedValue HandleWithUint16(JSThread *thread, uint32_t size, uint8_t *block, uint32_t indexedPosition,
119                                          EcmaRuntimeCallInfo *argv, const callbackfun &op, uint16_t &tag);
120    template<typename callbackfun>
121    static JSTaggedValue HandleWithInt16(JSThread *thread, uint32_t size, uint8_t *block, uint32_t indexedPosition,
122                                         EcmaRuntimeCallInfo *argv, const callbackfun &op, int16_t &tag);
123    template<typename callbackfun>
124    static JSTaggedValue HandleWithUint32(JSThread *thread, uint32_t size, uint8_t *block, uint32_t indexedPosition,
125                                          EcmaRuntimeCallInfo *argv, const callbackfun &op, uint32_t &tag);
126    template<typename callbackfun>
127    static JSTaggedValue HandleWithInt32(JSThread *thread, uint32_t size, uint8_t *block, uint32_t indexedPosition,
128                                         EcmaRuntimeCallInfo *argv, const callbackfun &op, int32_t &tag);
129    template<typename callbackfun>
130    static JSTaggedValue HandleWithBigInt64(JSThread *thread, uint32_t size, uint8_t *block, uint32_t indexedPosition,
131        EcmaRuntimeCallInfo *argv, const callbackfun &op, int64_t &tag, bool &lossless);
132    template<typename callbackfun>
133    static JSTaggedValue HandleWithBigUint64(JSThread *thread, uint32_t size, uint8_t *block, uint32_t indexedPosition,
134        EcmaRuntimeCallInfo *argv, const callbackfun &op, uint64_t &tag, bool &lossless);
135
136    static constexpr int ARGS_NUMBER = 2;
137};
138}  // namespace panda::ecmascript::builtins
139#endif  // ECMASCRIPT_BUILTINS_BUILTINS_MATH_H
140