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 
55 namespace panda::ecmascript::builtins {
56 enum class WaitResult: uint8_t {OK = 0, NOT_EQ, TIME_OUT};
57 
58 class BuiltinsAtomics : public base::BuiltinsBase {
59 public:
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 
GetAtomicsFunctions()85     static Span<const base::BuiltinFunctionEntry> GetAtomicsFunctions()
86     {
87         return Span<const base::BuiltinFunctionEntry>(ATOMICS_FUNCTIONS);
88     }
89 
90 private:
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