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_JS_STABLE_ARRAY_H
17#define ECMASCRIPT_JS_STABLE_ARRAY_H
18
19#include "ecmascript/base/typed_array_helper.h"
20#include "ecmascript/js_array.h"
21#include "ecmascript/js_dataview.h"
22#include "ecmascript/js_hclass.h"
23#include "ecmascript/js_typed_array.h"
24#include "ecmascript/js_tagged_value.h"
25
26namespace panda::ecmascript {
27class JSStableArray {
28public:
29    enum SeparatorFlag : int { MINUS_ONE = -1, MINUS_TWO = -2 };
30    static JSTaggedValue Push(JSHandle<JSArray> receiver, EcmaRuntimeCallInfo *argv);
31    static JSTaggedValue Push(JSHandle<JSSharedArray> receiver, EcmaRuntimeCallInfo *argv);
32    static JSTaggedValue Pop(JSHandle<JSArray> receiver, EcmaRuntimeCallInfo *argv);
33    static JSTaggedValue Pop(JSHandle<JSSharedArray> receiver, EcmaRuntimeCallInfo *argv);
34    static JSTaggedValue Splice(JSHandle<JSArray> receiver, EcmaRuntimeCallInfo *argv, uint32_t start,
35                                uint32_t insertCount, uint32_t actualDeleteCount,
36                                JSHandle<JSObject> newArrayHandle, uint32_t len);
37    static JSTaggedValue Splice(JSHandle<JSSharedArray> receiver, EcmaRuntimeCallInfo *argv, uint32_t start,
38                                uint32_t insertCount, uint32_t actualDeleteCount,
39                                JSHandle<JSObject> newArrayHandle, uint32_t len);
40    static JSTaggedValue Shift(JSHandle<JSArray> receiver, EcmaRuntimeCallInfo *argv);
41    static JSTaggedValue Shift(JSHandle<JSSharedArray> receiver, EcmaRuntimeCallInfo *argv);
42    static JSTaggedValue Join(JSHandle<JSArray> receiver, EcmaRuntimeCallInfo *argv);
43    static JSTaggedValue HandleFindIndexOfStable(JSThread *thread, JSHandle<JSObject> thisObjHandle,
44                                                 JSHandle<JSTaggedValue> callbackFnHandle,
45                                                 JSHandle<JSTaggedValue> thisArgHandle, uint32_t &k);
46    static JSTaggedValue HandleFindLastIndexOfStable(JSThread *thread, JSHandle<JSObject> thisObjHandle,
47                                                     JSHandle<JSTaggedValue> callbackFnHandle,
48                                                     JSHandle<JSTaggedValue> thisArgHandle, int64_t &k);
49    static JSTaggedValue HandleEveryOfStable(JSThread *thread, JSHandle<JSObject> thisObjHandle,
50                                             JSHandle<JSTaggedValue> callbackFnHandle,
51                                             JSHandle<JSTaggedValue> thisArgHandle, uint32_t &k);
52    static JSTaggedValue HandleSomeOfStable(JSThread *thread, JSHandle<JSObject> thisObjHandle,
53                                             JSHandle<JSTaggedValue> callbackFnHandle,
54                                             JSHandle<JSTaggedValue> thisArgHandle, uint32_t &k);
55    static JSTaggedValue HandleforEachOfStable(JSThread *thread, JSHandle<JSObject> thisObjHandle,
56                                               JSHandle<JSTaggedValue> callbackFnHandle,
57                                               JSHandle<JSTaggedValue> thisArgHandle, uint32_t len, uint32_t &k);
58    static JSTaggedValue IndexOf(JSThread *thread, JSHandle<JSTaggedValue> receiver,
59                                 JSHandle<JSTaggedValue> searchElement, uint32_t from, uint32_t len);
60    static JSTaggedValue LastIndexOf(JSThread *thread, JSHandle<JSTaggedValue> receiver,
61                                 JSHandle<JSTaggedValue> searchElement, uint32_t from, uint32_t len);
62    static JSTaggedValue Filter(JSHandle<JSObject> newArrayHandle, JSHandle<JSObject> thisObjHandle,
63                                 EcmaRuntimeCallInfo *argv, uint32_t &k, uint32_t &toIndex);
64    static JSTaggedValue Map(JSHandle<JSObject> newArrayHandle, JSHandle<JSObject> thisObjHandle,
65                                 EcmaRuntimeCallInfo *argv, uint32_t &k, uint32_t len);
66    static JSTaggedValue Reverse(JSThread *thread, JSHandle<JSObject> thisObjHandle,
67                                 int64_t &lower, uint32_t len);
68    static JSTaggedValue FastReverse(JSThread *thread, JSHandle<TaggedArray> elements,
69                                     int64_t &lower, uint32_t len, ElementsKind kind);
70    static JSTaggedValue Concat(JSThread *thread, JSHandle<JSObject> newArrayHandle,
71                                JSHandle<JSObject> thisObjHandle, int64_t &k, int64_t &n);
72    template<base::TypedArrayKind typedArrayKind = base::TypedArrayKind::NON_SHARED>
73    static JSTaggedValue FastCopyFromArrayToTypedArray(JSThread *thread, JSHandle<JSTypedArray> &target,
74                                                       DataViewType targetType, uint64_t targetOffset,
75                                                       uint32_t srcLength, JSHandle<JSObject> &obj);
76    static JSTaggedValue At(JSHandle<JSArray> receiver, EcmaRuntimeCallInfo *argv);
77    static JSTaggedValue At(JSHandle<JSSharedArray> receiver, EcmaRuntimeCallInfo *argv);
78    static JSTaggedValue With(JSThread *thread, JSHandle<JSArray> receiver,
79                              int64_t insertCount, int64_t index, JSHandle<JSTaggedValue> value);
80    static JSTaggedValue ToSpliced(JSHandle<JSArray> receiver, EcmaRuntimeCallInfo *argv,
81                                   int64_t argc, int64_t actualStart, int64_t actualSkipCount, int64_t insertCount);
82    static JSTaggedValue ToReversed(JSThread *thread, JSHandle<JSArray> receiver, int64_t insertCount);
83    static JSTaggedValue Reduce(JSThread *thread, JSHandle<JSObject> thisObjHandle,
84                                JSHandle<JSTaggedValue> callbackFnHandle,
85                                JSMutableHandle<JSTaggedValue> accumulator, int64_t &k, int64_t &len);
86    static JSTaggedValue Slice(JSThread *thread, JSHandle<JSObject> thisObjHandle, int64_t &k, int64_t &count);
87
88    static JSTaggedValue Sort(JSThread *thread, const JSHandle<JSObject> &thisObj,
89                              const JSHandle<JSTaggedValue> &callbackFnHandle);
90    static JSTaggedValue Fill(JSThread *thread, const JSHandle<JSObject> &thisObj,
91                              const JSHandle<JSTaggedValue> &value,
92                              int64_t start, int64_t end, int64_t len);
93    static JSTaggedValue HandleFindLastOfStable(JSThread *thread, JSHandle<JSObject> thisObjHandle,
94                                                JSHandle<JSTaggedValue> callbackFnHandle,
95                                                JSHandle<JSTaggedValue> thisArgHandle,
96                                                JSMutableHandle<JSTaggedValue> &kValue, int64_t &k);
97    static JSTaggedValue HandleReduceRightOfStable(JSThread *thread, JSHandle<JSObject> thisObjHandle,
98                                                   JSHandle<JSTaggedValue> callbackFnHandle,
99                                                   JSMutableHandle<JSTaggedValue> &accumulator,
100                                                   JSHandle<JSTaggedValue> thisArgHandle, int64_t &k);
101
102private:
103    static void SetSepValue(JSHandle<EcmaString> sepStringHandle, int &sep, uint32_t &sepLength);
104    enum class IndexOfType {
105        IndexOf,
106        LastIndexOf
107    };
108
109    struct IndexOfContext {
110        JSThread *thread;
111        JSHandle<JSTaggedValue> receiver;
112        JSHandle<JSTaggedValue> searchElement;
113        uint32_t fromIndex;
114        uint32_t length;
115    };
116
117    template <class Predicate>
118    static JSTaggedValue FindRawData(IndexOfContext &ctx, Predicate &&predicate);
119    template <class Predicate>
120    static JSTaggedValue FindLastRawData(IndexOfContext &ctx, Predicate &&predicate);
121    template <class Predicate>
122    static JSTaggedValue FindRawDataDispatch(IndexOfType type, IndexOfContext &ctx, Predicate &&predicate);
123
124    static JSTaggedValue IndexOfZero(IndexOfType type, IndexOfContext &ctx);
125    static JSTaggedValue IndexOfInt32(IndexOfType type, IndexOfContext &ctx, JSTaggedValue searchElement);
126    static JSTaggedValue IndexOfDouble(IndexOfType type, IndexOfContext &ctx, JSTaggedValue searchElement);
127    static JSTaggedValue IndexOfObjectAddress(IndexOfType type, IndexOfContext &ctx, JSTaggedValue searchElement);
128    static JSTaggedValue IndexOfString(IndexOfType type, IndexOfContext &ctx, JSTaggedValue searchElement);
129    static JSTaggedValue IndexOfBigInt(IndexOfType type, IndexOfContext &ctx, JSTaggedValue searchElement);
130    static JSTaggedValue IndexOfDispatch(IndexOfType type, IndexOfContext &ctx, JSTaggedValue searchElement);
131    static JSTaggedValue UpdateArrayCapacity(JSHandle<JSObject> &thisObjHandle, uint32_t &len,
132                                             uint32_t &insertCount, uint32_t &actualDeleteCount,
133                                             JSHandle<JSArray> &receiver, uint32_t &start,
134                                             JSThread *thread, bool &needTransition,
135                                             JSHandle<JSTaggedValue> &holeHandle,
136                                             EcmaRuntimeCallInfo *argv, JSHandle<JSTaggedValue> &thisObjVal,
137                                             JSHandle<JSTaggedValue> &lengthKey);
138    static void HandleArray(JSHandle<JSObject> &newArrayHandle, uint32_t &actualDeleteCount,
139                            JSThread *thread, uint32_t &start, JSHandle<JSObject> &thisObjHandle,
140                            JSHandle<JSTaggedValue> &holeHandle);
141    static JSTaggedValue JoinUseTreeString(const JSThread* thread, JSHandle<JSTaggedValue> receiverValue,
142                                       JSHandle<EcmaString> sepStringHandle, int sep,
143                                       CVector<JSHandle<EcmaString>>& vec);
144    inline static bool WorthUseTreeString(int sep, size_t allocateLength, uint32_t len);
145
146    // Allocate object larger than 256 need liner search in the free object list,
147    // so try to use tree string when the join result is larger than 256.
148    static constexpr size_t TREE_STRING_THRESHOLD = 256;
149    static constexpr size_t NUM_2 = 2;
150};
151}  // namespace panda::ecmascript
152#endif  // ECMASCRIPT_JS_STABLE_ARRAY_H
153