• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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_SHARED_ARRAY_H
17 #define ECMASCRIPT_BUILTINS_BUILTINS_SHARED_ARRAY_H
18 
19 #include "ecmascript/base/builtins_base.h"
20 
21 // List of functions in Shared Array, excluding the '@@' properties.
22 // V(name, func, length, stubIndex)
23 // where BuiltinsSharedArray::func refers to the native implementation of SharedArray[name].
24 //       kungfu::BuiltinsStubCSigns::stubIndex refers to the builtin stub index, or INVALID if no stub available.
25 #define BUILTIN_SHARED_ARRAY_FUNCTIONS(V)                      \
26     /* SharedArray.from ( items [ , mapfn [ , thisArg ] ] ) */ \
27     V("from", From, 1, INVALID)                                \
28     V("create", Create, 2, INVALID)                            \
29     /* SendableArray.isArray ( arg ) */                        \
30     V("isArray", IsArray, 1, INVALID)                          \
31     V("of", Of, 1, INVALID)                                    \
32     // fixme(hzzhouzebin) Support later.
33     // /* SharedArray.of ( ...items ) */                          \
34     // V("of", Of, 0, INVALID)
35 
36 // List of functions in SharedArray.prototype, excluding the constructor and '@@' properties.
37 // V(name, func, length, stubIndex)
38 // where BuiltinsSharedArray::func refers to the native implementation of SharedArray.prototype[name].
39 #define BUILTIN_SHARED_ARRAY_PROTOTYPE_FUNCTIONS(V)                              \
40     /* SharedArray.prototype.at ( index ) */                                     \
41     V("at", At, 1, INVALID)                                                      \
42     /* SharedArray.prototype.concat ( ...items ) */                              \
43     V("concat", Concat, 1, INVALID)                                              \
44     /* SharedArray.prototype.entries ( ) */                                      \
45     V("entries", Entries, 0, INVALID)                                            \
46     /* SharedArray.prototype.fill ( value [ , start [ , end ] ] ) */             \
47     V("fill", Fill, 1, INVALID)                                                  \
48     /* SharedArray.prototype.filter ( callbackfn [ , thisArg ] ) */              \
49     V("filter", Filter, 1, INVALID)                                              \
50     /* SharedArray.prototype.find ( predicate [ , thisArg ] ) */                 \
51     V("find", Find, 1, INVALID)                                                  \
52     /* SharedArray.prototype.findIndex ( predicate [ , thisArg ] ) */            \
53     V("findIndex", FindIndex, 1, INVALID)                                        \
54     /* SharedArray.prototype.forEach ( callbackfn [ , thisArg ] ) */             \
55     V("forEach", ForEach, 1, INVALID)                                            \
56     /* SharedArray.prototype.includes ( searchElement [ , fromIndex ] ) */       \
57     V("includes", Includes, 1, INVALID)                                          \
58     /* SharedArray.prototype.indexOf ( searchElement [ , fromIndex ] ) */        \
59     V("indexOf", IndexOf, 1, INVALID)                                            \
60     /* SharedArray.prototype.join ( separator ) */                               \
61     V("join", Join, 1, INVALID)                                                  \
62     /* SharedArray.prototype.keys ( ) */                                         \
63     V("keys", Keys, 0, INVALID)                                                  \
64     /* SharedArray.prototype.map ( callbackfn [ , thisArg ] ) */                 \
65     V("map", Map, 1, INVALID)                                                    \
66     /* SharedArray.prototype.pop ( ) */                                          \
67     V("pop", Pop, 0, INVALID)                                                    \
68     /* SharedArray.prototype.push ( ...items ) */                                \
69     V("push", Push, 1, INVALID)                                                  \
70     /* SharedArray.prototype.reduce ( callbackfn [ , initialValue ] ) */         \
71     V("reduce", Reduce, 1, INVALID)                                              \
72     /* SharedArray.prototype.shift ( ) */                                        \
73     V("shift", Shift, 0, INVALID)                                                \
74     /* SharedArray.prototype.slice ( start, end ) */                             \
75     V("slice", Slice, 2, INVALID)                                                \
76     /* SharedArray.prototype.sort ( comparefn ) */                               \
77     V("sort", Sort, 1, INVALID)                                                  \
78     /* SharedArray.prototype.toString ( ) */                                     \
79     V("toString", ToString, 0, INVALID)                                          \
80     /* SharedArray.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] ) */ \
81     V("toLocaleString", ToLocaleString, 0, INVALID)                              \
82     /* SharedArray.prototype.values ( ) */                                       \
83     /* SharedArray.prototype.unshift ( ...items ) */                             \
84     V("unshift", Unshift, 1, INVALID)                                            \
85     V("values", Values, 0, INVALID)                                              \
86     V("shrinkTo", ShrinkTo, 0, INVALID)                                          \
87     V("extendTo", ExtendTo, 0, INVALID)                                          \
88     /* SharedArray.prototype.splice ( start, deleteCount, ...items ) */          \
89     V("splice", Splice, 2, INVALID)                                              \
90     /* SharedArray.prototype.every ( callbackfn [ , thisArg ] ) */               \
91     V("every", Every, 1, INVALID)                                                \
92     /* SharedArray.prototype.some ( callbackfn [ , thisArg ] ) */                \
93     V("some", Some, 1, INVALID)                                                  \
94     /* SendableArray.prototype.lastIndexOf ( searchElement [ , fromIndex ] ) */  \
95     V("lastIndexOf", LastIndexOf, 1, INVALID)                                    \
96 	/* SharedArray.prototype.copyWithin ( target, start [ , end ] ) */           \
97     V("copyWithin", CopyWithin, 2, INVALID)                                      \
98 	/* SharedArray.prototype.reduceRight ( callbackfn [ , initialValue ] ) */    \
99     V("reduceRight", ReduceRight, 1, INVALID)                                    \
100     /*  SharedArray.prototype.reverse ( )               */                       \
101     V("reverse", Reverse, 0, INVALID)                                            \
102 	/* SharedArray.prototype.findLast ( predicate [ , thisArg ] ) */             \
103     V("findLast", FindLast, 1, INVALID)                                          \
104     /* SharedArray.prototype.findLastIndex ( predicate [ , thisArg ] ) */        \
105     V("findLastIndex", FindLastIndex, 1, INVALID)                                \
106     // fixme(hzzhouzebin) Support later.
107     // /* SharedArray.prototype.with ( index, value ) */                            \
108     // V("with", With, 2, INVALID)                                                  \
109     // /* SharedArray.prototype.toReversed ( ) */                                   \
110     // V("toReversed", ToReversed, 0, INVALID)                                      \
111     // /* SharedArray.prototype.toSorted ( comparefn ) */                           \
112     // V("toSorted", ToSorted, 1, INVALID)                                          \
113     // /* SharedArray.prototype.toSpliced ( start, skipCount, ...items ) */         \
114     // V("toSpliced", ToSpliced, 2, INVALID)
115 
116 namespace panda::ecmascript::builtins {
117 class BuiltinsSharedArray : public base::BuiltinsBase {
118 public:
119     static JSTaggedValue ArrayConstructor(EcmaRuntimeCallInfo *argv);
120     static JSTaggedValue From(EcmaRuntimeCallInfo *argv);
121     static JSTaggedValue Create(EcmaRuntimeCallInfo *argv);
122     static JSTaggedValue IsArray(EcmaRuntimeCallInfo *argv);
123     static JSTaggedValue Species(EcmaRuntimeCallInfo *argv);
124 
125     // prototype
126     static JSTaggedValue Concat(EcmaRuntimeCallInfo *argv);
127     static JSTaggedValue Entries(EcmaRuntimeCallInfo *argv);
128     static JSTaggedValue Fill(EcmaRuntimeCallInfo *argv);
129     static JSTaggedValue Filter(EcmaRuntimeCallInfo *argv);
130     static JSTaggedValue Find(EcmaRuntimeCallInfo *argv);
131     static JSTaggedValue FindIndex(EcmaRuntimeCallInfo *argv);
132     static JSTaggedValue ForEach(EcmaRuntimeCallInfo *argv);
133     static JSTaggedValue IndexOf(EcmaRuntimeCallInfo *argv);
134     static JSTaggedValue Join(EcmaRuntimeCallInfo *argv);
135     static JSTaggedValue Keys(EcmaRuntimeCallInfo *argv);
136     static JSTaggedValue Map(EcmaRuntimeCallInfo *argv);
137     static JSTaggedValue Pop(EcmaRuntimeCallInfo *argv);
138     static JSTaggedValue Push(EcmaRuntimeCallInfo *argv);
139     static JSTaggedValue Reduce(EcmaRuntimeCallInfo *argv);
140     static JSTaggedValue Shift(EcmaRuntimeCallInfo *argv);
141     static JSTaggedValue Slice(EcmaRuntimeCallInfo *argv);
142     static JSTaggedValue Splice(EcmaRuntimeCallInfo *argv);
143     static JSTaggedValue Sort(EcmaRuntimeCallInfo *argv);
144     static JSTaggedValue ToString(EcmaRuntimeCallInfo *argv);
145     static JSTaggedValue ToLocaleString(EcmaRuntimeCallInfo *argv);
146     static JSTaggedValue Unshift(EcmaRuntimeCallInfo *argv);
147     static JSTaggedValue Values(EcmaRuntimeCallInfo *argv);
148     static JSTaggedValue Unscopables(EcmaRuntimeCallInfo *argv);
149     static JSTaggedValue Includes(EcmaRuntimeCallInfo *argv);
150     static JSTaggedValue At(EcmaRuntimeCallInfo *argv);
151     static JSTaggedValue ShrinkTo(EcmaRuntimeCallInfo *argv);
152     static JSTaggedValue ExtendTo(EcmaRuntimeCallInfo *argv);
153     static JSTaggedValue Every(EcmaRuntimeCallInfo *argv);
154     static JSTaggedValue Some(EcmaRuntimeCallInfo *argv);
155     static JSTaggedValue LastIndexOf(EcmaRuntimeCallInfo *argv);
156     static JSTaggedValue Of(EcmaRuntimeCallInfo *argv);
157     static JSTaggedValue CopyWithin(EcmaRuntimeCallInfo *argv);
158     static JSTaggedValue FindLast(EcmaRuntimeCallInfo *argv);
159     static JSTaggedValue FindLastIndex(EcmaRuntimeCallInfo *argv);
160     static JSTaggedValue Reverse(EcmaRuntimeCallInfo *argv);
161     static JSTaggedValue ReduceRight(EcmaRuntimeCallInfo *argv);
162 
163     // Excluding the '@@' internal properties
GetSharedArrayFunctions()164     static Span<const base::BuiltinFunctionEntry> GetSharedArrayFunctions()
165     {
166         return Span<const base::BuiltinFunctionEntry>(SENDABLE_ARRAY_FUNCTIONS);
167     }
168 
169     // Excluding the constructor and '@@' internal properties.
GetSharedArrayPrototypeFunctions()170     static Span<const base::BuiltinFunctionEntry> GetSharedArrayPrototypeFunctions()
171     {
172         return Span<const base::BuiltinFunctionEntry>(SENDABLE_ARRAY_PROTOTYPE_FUNCTIONS);
173     }
174 
GetNumPrototypeInlinedProperties()175     static size_t GetNumPrototypeInlinedProperties()
176     {
177         // 4 : 4 More inlined entries in SharedArray.prototype for the following functions/accessors:
178         //   (1) 'length' accessor
179         //   (2) SharedArray.prototype.constructor, i.e. Array()
180         //   (3) SharedArray.prototype[@@iterator]()
181         //   (4) SharedArray.prototype[@@unscopables]()
182         return GetSharedArrayPrototypeFunctions().Size() + 4;
183     }
184     static JSTaggedValue ReduceUnStableJSArray(JSThread *thread, JSHandle<JSTaggedValue> &thisHandle,
185         JSHandle<JSObject> &thisObjHandle, int64_t k, int64_t len, JSMutableHandle<JSTaggedValue> &accumulator,
186         JSHandle<JSTaggedValue> &callbackFnHandle);
187 
188     static JSTaggedValue FilterArray(JSThread *thread, JSHandle<JSTaggedValue> &thisArgHandle,
189         JSHandle<JSTaggedValue> &thisObjVal, JSHandle<JSObject>& newArrayHandle,
190         JSHandle<JSTaggedValue> &callbackFnHandle);
191 
GetPrototypeProperties()192     static Span<const std::pair<std::string_view, bool>> GetPrototypeProperties()
193     {
194         return Span<const std::pair<std::string_view, bool>>(ARRAY_PROTOTYPE_PROPERTIES);
195     }
GetFunctionProperties()196     static Span<const std::pair<std::string_view, bool>> GetFunctionProperties()
197     {
198         return Span<const std::pair<std::string_view, bool>>(ARRAY_FUNCTION_PROPERTIES);
199     }
200 
201     static inline int64_t ConvertTagValueToInteger(JSThread *thread, JSHandle<JSTaggedValue>& number, int64_t len);
202     static inline int64_t GetNumberArgVal(JSThread *thread, EcmaRuntimeCallInfo *argv, uint32_t idx, int64_t len,
203                                           int64_t defVal);
204     static inline int64_t GetNumberArgValThrow(JSThread *thread, EcmaRuntimeCallInfo *argv, uint32_t idx,
205                                                int64_t len, const char* err);
206 
207     static inline void SetElementValue(JSThread *thread, JSHandle<JSObject> arrHandle, uint32_t key,
208                                        const JSHandle<JSTaggedValue> &value);
209     static inline JSTaggedValue FastReverse(JSThread *thread, JSHandle<TaggedArray>& elements,
210                                             uint32_t lower, uint32_t len, ElementsKind kind);
211 
212 private:
213     static inline JSTaggedValue GetElementByKey(JSThread *thread, JSHandle<JSObject>& thisObjHandle, uint32_t index);
214     static inline JSTaggedValue PopInner(EcmaRuntimeCallInfo *argv, JSHandle<JSTaggedValue> &thisHandle,
215                                          JSHandle<JSObject> &thisObjHandle);
216     static inline int64_t FillNewTaggedArray(JSThread *thread, EcmaRuntimeCallInfo *argv, int argc,
217                                              int64_t newArrayIdx, JSHandle<TaggedArray> &eleArray);
218     static inline int64_t CalNewArrayLen(JSThread *thread, EcmaRuntimeCallInfo *argv, int argc);
219     static inline JSTaggedValue IndexOfStable(EcmaRuntimeCallInfo *argv, JSThread *thread,
220                                               const JSHandle<JSTaggedValue> &thisHandle);
221     static inline JSTaggedValue FromSharedArray(JSThread *thread, const JSHandle<JSTaggedValue>& items,
222                                                 JSHandle<JSObject>& newArrayHandle);
223     static inline JSTaggedValue FromArrayNoMaping(JSThread *thread, const JSHandle<JSTaggedValue>& items,
224                                                   JSHandle<JSObject>& newArrayHandle);
225     template<bool itemIsSharedArray>
226     static inline JSTaggedValue FromArray(JSThread *thread, const JSHandle<JSTaggedValue>& items,
227                                           const JSHandle<JSTaggedValue>& thisArgHandle,
228                                           const JSHandle<JSTaggedValue> mapfn,
229                                           JSHandle<JSObject>& newArrayHandle);
230 
231 #define BUILTIN_SENDABLE_ARRAY_FUNCTION_ENTRY(name, method, length, id) \
232     base::BuiltinFunctionEntry::Create(name, BuiltinsSharedArray::method, length, kungfu::BuiltinsStubCSigns::id),
233 
234     static constexpr std::array SENDABLE_ARRAY_FUNCTIONS  = {
235         BUILTIN_SHARED_ARRAY_FUNCTIONS(BUILTIN_SENDABLE_ARRAY_FUNCTION_ENTRY)
236     };
237     static constexpr std::array SENDABLE_ARRAY_PROTOTYPE_FUNCTIONS = {
238         BUILTIN_SHARED_ARRAY_PROTOTYPE_FUNCTIONS(BUILTIN_SENDABLE_ARRAY_FUNCTION_ENTRY)
239     };
240 #undef BUILTIN_SENDABLE_ARRAY_FUNCTION_ENTRY
241 
242     static JSTaggedValue IndexOfSlowPath(
243         EcmaRuntimeCallInfo *argv, JSThread *thread, const JSHandle<JSTaggedValue> &thisHandle);
244 
245     static JSTaggedValue IndexOfSlowPath(
246         EcmaRuntimeCallInfo *argv, JSThread *thread, const JSHandle<JSTaggedValue> &thisObjVal,
247         int64_t length, int64_t fromIndex);
248 
249     static JSTaggedValue LastIndexOfSlowPath(EcmaRuntimeCallInfo *argv, JSThread *thread,
250                                              const JSHandle<JSTaggedValue> &thisHandle);
251     static JSTaggedValue LastIndexOfSlowPath(EcmaRuntimeCallInfo *argv, JSThread *thread,
252                                              const JSHandle<JSTaggedValue> &thisObjVal, int64_t fromIndex);
253     static JSTaggedValue ToLocaleStringInternalHandle(EcmaRuntimeCallInfo *argv, JSThread *thread,
254             EcmaContext *context, ObjectFactory *factory, const JSHandle<JSTaggedValue> &thisHandle, int64_t len);
255     static JSTaggedValue ReduceRightInternalHandle(EcmaRuntimeCallInfo *argv, JSThread *thread,
256             const JSHandle<JSTaggedValue> &thisHandle, JSHandle<JSObject>& thisObjHandle, uint32_t argc, int64_t len);
257 
258 #define ARRAY_PROPERTIES_PAIR(name, func, length, id) \
259     std::pair<std::string_view, bool>(name, false),
260 
261     static constexpr std::array ARRAY_PROTOTYPE_PROPERTIES = {
262         std::pair<std::string_view, bool>("length", false),
263         std::pair<std::string_view, bool>("constructor", false),
264         BUILTIN_SHARED_ARRAY_PROTOTYPE_FUNCTIONS(ARRAY_PROPERTIES_PAIR)
265         std::pair<std::string_view, bool>("[Symbol.iterator]", false),
266         std::pair<std::string_view, bool>("[Symbol.unscopables]", false)
267     };
268     static constexpr std::array ARRAY_FUNCTION_PROPERTIES = {
269         std::pair<std::string_view, bool>("length", false),
270         std::pair<std::string_view, bool>("name", false),
271         std::pair<std::string_view, bool>("prototype", false),
272         BUILTIN_SHARED_ARRAY_FUNCTIONS(ARRAY_PROPERTIES_PAIR)
273         std::pair<std::string_view, bool>("[Symbol.species]", true),
274     };
275     static JSTaggedValue CheckElementMeetReq(JSThread *thread,
276                                              JSHandle<JSTaggedValue> &thisObjVal,
277                                              JSHandle<JSTaggedValue> &callbackFnHandle, bool isSome);
278 #undef ARRAY_PROPERTIES_PAIR
279 
280 #define ARRAY_CHECK_SHARED_ARRAY(errMsg)                                            \
281     JSHandle<JSTaggedValue> thisHandle = GetThis(argv);                             \
282     if (UNLIKELY(!thisHandle->IsJSSharedArray())) {                                 \
283         auto error = ContainerError::BindError(thread, errMsg);                     \
284         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); \
285     }
286 };
287 }  // namespace panda::ecmascript::builtins
288 
289 #endif  // ECMASCRIPT_BUILTINS_BUILTINS_SHARED_ARRAY_H
290