• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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