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_JSHANDLE_H 17 #define ECMASCRIPT_JSHANDLE_H 18 19 #include <type_traits> 20 21 #include "ecmascript/ecma_handle_scope-inl.h" 22 #include "ecmascript/js_tagged_value.h" 23 #include "handle_base.h" 24 25 namespace panda::test { 26 class JSHandleTest; 27 } // namespace panda::test 28 29 namespace panda::ecmascript { 30 class TaggedArray; 31 class LinkedHashMap; 32 class LinkedHashSet; 33 class NameDictionary; 34 35 template <typename T> 36 class JSHandle : public HandleBase { 37 public: JSHandle()38 inline explicit JSHandle() : HandleBase(reinterpret_cast<uintptr_t>(nullptr)) {} 39 ~JSHandle() = default; 40 DEFAULT_NOEXCEPT_MOVE_SEMANTIC(JSHandle); 41 DEFAULT_COPY_SEMANTIC(JSHandle); 42 JSHandle(const JSThread * thread,JSTaggedValue value)43 explicit JSHandle(const JSThread *thread, JSTaggedValue value) : HandleBase() 44 { 45 address_ = EcmaHandleScope::NewHandle(const_cast<JSThread *>(thread), value.GetRawData()); 46 } 47 JSHandle(const JSThread * thread,const ObjectHeader * value)48 explicit JSHandle(const JSThread *thread, const ObjectHeader *value) : HandleBase() 49 { 50 address_ = EcmaHandleScope::NewHandle(const_cast<JSThread *>(thread), JSTaggedValue(value).GetRawData()); 51 } 52 JSHandle(const JSThread * thread,const TaggedObject * value)53 explicit JSHandle(const JSThread *thread, const TaggedObject *value) : HandleBase() 54 { 55 address_ = EcmaHandleScope::NewHandle(const_cast<JSThread *>(thread), JSTaggedValue(value).GetRawData()); 56 } 57 58 template <typename S> JSHandle(const JSHandle<S> & handle)59 explicit JSHandle(const JSHandle<S> &handle) : HandleBase(handle.GetAddress()) 60 { 61 } 62 63 template <typename S> Cast(const JSHandle<S> & handle)64 inline static JSHandle<T> Cast(const JSHandle<S> &handle) 65 { 66 T::Cast(handle.GetTaggedValue().GetTaggedObject()); 67 return JSHandle<T>(handle.GetAddress()); 68 } 69 GetTaggedValue()70 inline JSTaggedValue GetTaggedValue() const 71 { 72 if (GetAddress() == 0U) { 73 return JSTaggedValue::Undefined(); 74 } 75 return *(reinterpret_cast<JSTaggedValue *>(GetAddress())); // NOLINT(clang-analyzer-core.NullDereference) 76 } 77 GetTaggedType()78 inline JSTaggedType GetTaggedType() const 79 { 80 if (GetAddress() == 0U) { 81 return JSTaggedValue::Undefined().GetRawData(); 82 } 83 return *reinterpret_cast<JSTaggedType *>(GetAddress()); // NOLINT(clang-analyzer-core.NullDereference) 84 } 85 86 inline T *operator*() const 87 { 88 return T::Cast(GetTaggedValue().GetTaggedObject()); 89 } 90 91 inline T *operator->() const 92 { 93 return T::Cast(GetTaggedValue().GetTaggedObject()); 94 } 95 96 inline bool operator==(const JSHandle<T> &other) const 97 { 98 return GetTaggedType() == other.GetTaggedType(); 99 } 100 101 inline bool operator!=(const JSHandle<T> &other) const 102 { 103 return GetTaggedType() != other.GetTaggedType(); 104 } 105 IsEmpty()106 inline bool IsEmpty() const 107 { 108 return GetAddress() == 0U; 109 } 110 111 template <typename R> GetObject()112 R *GetObject() const 113 { 114 return reinterpret_cast<R *>(GetTaggedValue().GetTaggedObject()); 115 } 116 JSHandle(uintptr_t slot)117 inline explicit JSHandle(uintptr_t slot) : HandleBase(slot) 118 { 119 if (!std::is_convertible<T *, JSTaggedValue *>::value) { 120 T::Cast((*reinterpret_cast<JSTaggedValue *>(slot)).GetTaggedObject()); 121 } 122 } 123 Dump()124 void Dump() const DUMP_API_ATTR 125 { 126 GetTaggedValue().D(); 127 } 128 129 private: JSHandle(const JSTaggedType * slot)130 inline explicit JSHandle(const JSTaggedType *slot) : HandleBase(reinterpret_cast<uintptr_t>(slot)) {} JSHandle(const T * const * slot)131 inline explicit JSHandle(const T *const *slot) : HandleBase(reinterpret_cast<uintptr_t>(slot)) {} 132 133 friend class EcmaVM; 134 friend class GlobalEnv; 135 friend class JSHandleTest; 136 friend class GlobalHandleCollection; 137 }; 138 139 template <> 140 inline JSTaggedValue *JSHandle<JSTaggedValue>::operator->() const 141 { 142 return reinterpret_cast<JSTaggedValue *>(GetAddress()); 143 } 144 145 template <> 146 inline JSTaggedValue *JSHandle<JSTaggedValue>::operator*() const 147 { 148 return reinterpret_cast<JSTaggedValue *>(GetAddress()); 149 } 150 151 template <> 152 inline JSTaggedNumber *JSHandle<JSTaggedNumber>::operator->() const 153 { 154 return reinterpret_cast<JSTaggedNumber *>(GetAddress()); 155 } 156 157 template <> 158 inline JSTaggedNumber *JSHandle<JSTaggedNumber>::operator*() const 159 { 160 return reinterpret_cast<JSTaggedNumber *>(GetAddress()); 161 } 162 163 template <typename T> 164 class JSMutableHandle : public JSHandle<T> { 165 public: 166 JSMutableHandle() = default; 167 ~JSMutableHandle() = default; 168 DEFAULT_NOEXCEPT_MOVE_SEMANTIC(JSMutableHandle); 169 DEFAULT_COPY_SEMANTIC(JSMutableHandle); 170 JSMutableHandle(const JSThread * thread,JSTaggedValue value)171 explicit JSMutableHandle(const JSThread *thread, JSTaggedValue value) : JSHandle<T>(thread, value) {} JSMutableHandle(const JSThread * thread,const TaggedArray * value)172 explicit JSMutableHandle(const JSThread *thread, const TaggedArray *value) : JSHandle<T>(thread, value) {} 173 template <typename S> JSMutableHandle(const JSThread * thread,const JSHandle<S> & handle)174 explicit JSMutableHandle(const JSThread *thread, const JSHandle<S> &handle) 175 : JSHandle<T>(thread, handle.GetTaggedValue()) 176 { 177 } 178 179 template <typename S> JSMutableHandle(const JSHandle<S> & handle)180 explicit JSMutableHandle(const JSHandle<S> &handle) : JSHandle<T>(handle) 181 { 182 } 183 Update(JSTaggedValue value)184 void Update(JSTaggedValue value) 185 { 186 auto addr = reinterpret_cast<JSTaggedValue *>(this->GetAddress()); 187 *addr = value; 188 } 189 190 template <typename S> Update(const JSHandle<S> & handle)191 void Update(const JSHandle<S> &handle) 192 { 193 auto addr = reinterpret_cast<JSTaggedValue *>(this->GetAddress()); 194 *addr = handle.GetTaggedValue(); 195 } 196 }; 197 } // namespace panda::ecmascript 198 199 #endif // ECMASCRIPT_JSHANDLE_H 200