1/*
2 * Copyright (c) 2021-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_BASE_BUILTINS_BASE_H
17#define ECMASCRIPT_BASE_BUILTINS_BASE_H
18
19#include "ecmascript/ecma_runtime_call_info.h"
20#include "ecmascript/ecma_string.h"
21#include "ecmascript/global_env_constants-inl.h"
22#include "ecmascript/js_tagged_value.h"
23#include "ecmascript/object_factory.h"
24#include "ecmascript/runtime_call_id.h"
25#include "ecmascript/tagged_array.h"
26
27namespace panda::ecmascript {
28class JSArray;
29namespace base {
30class BuiltinConstantEntry {
31public:
32    constexpr BuiltinConstantEntry(std::string_view name, JSTaggedValue value)
33        : name_(name), rawTaggedValue_(value.GetRawData()) {}
34
35    static constexpr BuiltinConstantEntry Create(std::string_view name, JSTaggedValue value)
36    {
37        return BuiltinConstantEntry(name, value);
38    }
39
40    constexpr std::string_view GetName() const
41    {
42        return name_;
43    }
44
45    constexpr JSTaggedValue GetTaggedValue() const
46    {
47        return JSTaggedValue(rawTaggedValue_);
48    }
49
50private:
51    std::string_view name_;
52    JSTaggedType rawTaggedValue_;
53};
54
55class BuiltinsPropertyConfig {
56public:
57    constexpr BuiltinsPropertyConfig(std::string_view name, bool isAccessor, bool writable,
58        bool enumerable, bool configurable)
59        : name_(name), isAccessor_(isAccessor), writable_(writable),
60          enumerable_(enumerable), configurable_(configurable) {}
61
62    constexpr std::string_view GetName() const
63    {
64        return name_;
65    }
66
67    constexpr bool GetIsAccessor() const
68    {
69        return isAccessor_;
70    }
71
72    constexpr bool GetWritable() const
73    {
74        return writable_;
75    }
76
77    constexpr bool GetEnumerable() const
78    {
79        return enumerable_;
80    }
81
82    constexpr bool GetConfigurable() const
83    {
84        return configurable_;
85    }
86
87private:
88    std::string_view name_;
89    bool isAccessor_ {false};
90    bool writable_ {false};
91    bool enumerable_ {false};
92    bool configurable_ {false};
93};
94
95class BuiltinFunctionEntry {
96public:
97    static constexpr int LENGTH_BITS_SIZE = 8;
98    static constexpr int BUILTIN_ID_BITS_SIZE = 16;
99    // Assures the bits are enough to represent all builtin stubs.
100    static_assert(kungfu::BuiltinsStubCSigns::NUM_OF_BUILTINS_STUBS <= (1u << BUILTIN_ID_BITS_SIZE));
101
102    using LengthBits = panda::BitField<int, 0, LENGTH_BITS_SIZE>;
103    using BuiltinIdBits = LengthBits::NextField<kungfu::BuiltinsStubCSigns::ID, BUILTIN_ID_BITS_SIZE>;
104    using IsConstructorBit = BuiltinIdBits::NextFlag;
105    using IsAccessorBit = IsConstructorBit::NextFlag;
106
107    template <class... BitFieldArgs>
108    static constexpr BuiltinFunctionEntry Create(std::string_view name, EcmaEntrypoint entrypoint,
109                                                 int length, kungfu::BuiltinsStubCSigns::ID builtinId)
110    {
111        static_assert((std::is_same_v<typename BitFieldArgs::ValueType, bool> && ...),
112                      "Only 1-bit fields are available in BitFieldArgs");
113        uint64_t bitfield = 0;
114        bitfield |= LengthBits::Encode(length);
115        bitfield |= BuiltinIdBits::Encode(builtinId);
116        // Traverses BitFieldArgs (IsConstructorBit, IsAccessorBit, etc.)
117        ((bitfield |= BitFieldArgs::Encode(true)), ...);
118        return BuiltinFunctionEntry(name, entrypoint, bitfield);
119    }
120
121    constexpr std::string_view GetName() const
122    {
123        return name_;
124    }
125
126    constexpr EcmaEntrypoint GetEntrypoint() const
127    {
128        return entrypoint_;
129    }
130
131    constexpr int GetLength() const
132    {
133        return LengthBits::Decode(bitfield_);
134    }
135
136    constexpr kungfu::BuiltinsStubCSigns::ID GetBuiltinStubId() const
137    {
138        return BuiltinIdBits::Decode(bitfield_);
139    }
140
141    constexpr bool IsConstructor() const
142    {
143        return IsConstructorBit::Decode(bitfield_);
144    }
145
146    constexpr bool IsAccessor() const
147    {
148        return IsAccessorBit::Decode(bitfield_);
149    }
150
151private:
152    std::string_view name_;
153    EcmaEntrypoint entrypoint_;
154    uint64_t bitfield_;
155
156    constexpr BuiltinFunctionEntry(std::string_view name, EcmaEntrypoint entrypoint, uint64_t bitfield)
157        : name_(name), entrypoint_(entrypoint), bitfield_(bitfield) {}
158};
159
160class BuiltinsBase {
161public:
162    enum ArgsPosition : uint32_t { FIRST = 0, SECOND, THIRD, FOURTH, FIFTH };
163    static JSHandle<TaggedArray> GetArgsArray(EcmaRuntimeCallInfo *msg);
164    static inline JSHandle<JSTaggedValue> GetConstructor(EcmaRuntimeCallInfo *msg)
165    {
166        return msg->GetFunction();
167    }
168
169    static inline JSHandle<JSTaggedValue> GetThis(EcmaRuntimeCallInfo *msg)
170    {
171        return msg->GetThis();
172    }
173
174    static inline JSHandle<JSTaggedValue> GetNewTarget(EcmaRuntimeCallInfo *msg)
175    {
176        return msg->GetNewTarget();
177    }
178
179    static inline JSHandle<JSTaggedValue> GetCallArg(EcmaRuntimeCallInfo *msg, uint32_t position)
180    {
181        if (position >= msg->GetArgsNumber()) {
182            JSThread *thread = msg->GetThread();
183            return thread->GlobalConstants()->GetHandledUndefined();
184        }
185        return msg->GetCallArg(position);
186    }
187
188    static inline JSTaggedValue GetTaggedInt(int32_t value)
189    {
190        return JSTaggedValue(value);
191    }
192
193    static inline JSTaggedValue GetTaggedInt64(int64_t value)
194    {
195        return JSTaggedValue(value);
196    }
197
198    static inline JSTaggedValue GetTaggedDouble(double value)
199    {
200        return JSTaggedValue(value);
201    }
202
203    static inline JSTaggedValue GetTaggedBoolean(bool value)
204    {
205        return JSTaggedValue(value);
206    }
207
208    static inline JSTaggedValue GetTaggedString(JSThread *thread, const char *str)
209    {
210        return thread->GetEcmaVM()->GetFactory()->NewFromASCII(str).GetTaggedValue();
211    }
212};
213}  // namespace base
214}  // namespace panda::ecmascript
215
216#endif  // ECMASCRIPT_BASE_BUILTINS_BASE_H
217