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 27 namespace panda::ecmascript { 28 class JSArray; 29 namespace base { 30 class BuiltinConstantEntry { 31 public: BuiltinConstantEntry(std::string_view name,JSTaggedValue value)32 constexpr BuiltinConstantEntry(std::string_view name, JSTaggedValue value) 33 : name_(name), rawTaggedValue_(value.GetRawData()) {} 34 Create(std::string_view name,JSTaggedValue value)35 static constexpr BuiltinConstantEntry Create(std::string_view name, JSTaggedValue value) 36 { 37 return BuiltinConstantEntry(name, value); 38 } 39 GetName()40 constexpr std::string_view GetName() const 41 { 42 return name_; 43 } 44 GetTaggedValue()45 constexpr JSTaggedValue GetTaggedValue() const 46 { 47 return JSTaggedValue(rawTaggedValue_); 48 } 49 50 private: 51 std::string_view name_; 52 JSTaggedType rawTaggedValue_; 53 }; 54 55 class BuiltinsPropertyConfig { 56 public: BuiltinsPropertyConfig(std::string_view name,bool isAccessor,bool writable,bool enumerable,bool configurable)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 GetName()62 constexpr std::string_view GetName() const 63 { 64 return name_; 65 } 66 GetIsAccessor()67 constexpr bool GetIsAccessor() const 68 { 69 return isAccessor_; 70 } 71 GetWritable()72 constexpr bool GetWritable() const 73 { 74 return writable_; 75 } 76 GetEnumerable()77 constexpr bool GetEnumerable() const 78 { 79 return enumerable_; 80 } 81 GetConfigurable()82 constexpr bool GetConfigurable() const 83 { 84 return configurable_; 85 } 86 87 private: 88 std::string_view name_; 89 bool isAccessor_ {false}; 90 bool writable_ {false}; 91 bool enumerable_ {false}; 92 bool configurable_ {false}; 93 }; 94 95 class BuiltinFunctionEntry { 96 public: 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> Create(std::string_view name,EcmaEntrypoint entrypoint,int length,kungfu::BuiltinsStubCSigns::ID builtinId)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 GetName()121 constexpr std::string_view GetName() const 122 { 123 return name_; 124 } 125 GetEntrypoint()126 constexpr EcmaEntrypoint GetEntrypoint() const 127 { 128 return entrypoint_; 129 } 130 GetLength()131 constexpr int GetLength() const 132 { 133 return LengthBits::Decode(bitfield_); 134 } 135 GetBuiltinStubId()136 constexpr kungfu::BuiltinsStubCSigns::ID GetBuiltinStubId() const 137 { 138 return BuiltinIdBits::Decode(bitfield_); 139 } 140 IsConstructor()141 constexpr bool IsConstructor() const 142 { 143 return IsConstructorBit::Decode(bitfield_); 144 } 145 IsAccessor()146 constexpr bool IsAccessor() const 147 { 148 return IsAccessorBit::Decode(bitfield_); 149 } 150 151 private: 152 std::string_view name_; 153 EcmaEntrypoint entrypoint_; 154 uint64_t bitfield_; 155 BuiltinFunctionEntry(std::string_view name,EcmaEntrypoint entrypoint,uint64_t bitfield)156 constexpr BuiltinFunctionEntry(std::string_view name, EcmaEntrypoint entrypoint, uint64_t bitfield) 157 : name_(name), entrypoint_(entrypoint), bitfield_(bitfield) {} 158 }; 159 160 class BuiltinsBase { 161 public: 162 enum ArgsPosition : uint32_t { FIRST = 0, SECOND, THIRD, FOURTH, FIFTH }; 163 static JSHandle<TaggedArray> GetArgsArray(EcmaRuntimeCallInfo *msg); GetConstructor(EcmaRuntimeCallInfo * msg)164 static inline JSHandle<JSTaggedValue> GetConstructor(EcmaRuntimeCallInfo *msg) 165 { 166 return msg->GetFunction(); 167 } 168 GetThis(EcmaRuntimeCallInfo * msg)169 static inline JSHandle<JSTaggedValue> GetThis(EcmaRuntimeCallInfo *msg) 170 { 171 return msg->GetThis(); 172 } 173 GetNewTarget(EcmaRuntimeCallInfo * msg)174 static inline JSHandle<JSTaggedValue> GetNewTarget(EcmaRuntimeCallInfo *msg) 175 { 176 return msg->GetNewTarget(); 177 } 178 GetCallArg(EcmaRuntimeCallInfo * msg,uint32_t position)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 GetTaggedInt(int32_t value)188 static inline JSTaggedValue GetTaggedInt(int32_t value) 189 { 190 return JSTaggedValue(value); 191 } 192 GetTaggedInt64(int64_t value)193 static inline JSTaggedValue GetTaggedInt64(int64_t value) 194 { 195 return JSTaggedValue(value); 196 } 197 GetTaggedDouble(double value)198 static inline JSTaggedValue GetTaggedDouble(double value) 199 { 200 return JSTaggedValue(value); 201 } 202 GetTaggedBoolean(bool value)203 static inline JSTaggedValue GetTaggedBoolean(bool value) 204 { 205 return JSTaggedValue(value); 206 } 207 GetTaggedString(JSThread * thread,const char * str)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