• 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_JS_HCLASS_INL_H
17 #define ECMASCRIPT_JS_HCLASS_INL_H
18 
19 #include "ecmascript/js_hclass.h"
20 
21 #include "ecmascript/layout_info-inl.h"
22 #include "ecmascript/byte_array.h"
23 #include "ecmascript/mem/assert_scope.h"
24 #include "ecmascript/transitions_dictionary.h"
25 
26 namespace panda::ecmascript {
Cast(const TaggedObject * object)27 inline JSHClass *JSHClass::Cast(const TaggedObject *object)
28 {
29     ASSERT(JSTaggedValue(object).IsJSHClass());
30     return static_cast<JSHClass *>(const_cast<TaggedObject *>(object));
31 }
32 
AddTransitions(const JSThread * thread,const JSHandle<JSHClass> & parent,const JSHandle<JSHClass> & child,const JSHandle<JSTaggedValue> & key,PropertyAttributes attributes)33 void JSHClass::AddTransitions(const JSThread *thread, const JSHandle<JSHClass> &parent, const JSHandle<JSHClass> &child,
34                               const JSHandle<JSTaggedValue> &key, PropertyAttributes attributes)
35 {
36     JSTaggedValue transitions = parent->GetTransitions();
37     if (transitions.IsUndefined()) {
38         JSTaggedValue weakChild = JSTaggedValue(child.GetTaggedValue().CreateAndGetWeakRef());
39         parent->SetTransitions(thread, weakChild);
40         return;
41     }
42     JSMutableHandle<TransitionsDictionary> dict(thread, JSTaggedValue::Undefined());
43     if (transitions.IsWeak()) {
44         auto cachedHClass = JSHClass::Cast(transitions.GetTaggedWeakRef());
45         uint32_t last = cachedHClass->NumberOfProps() - 1;
46         LayoutInfo *layoutInfo = LayoutInfo::Cast(cachedHClass->GetLayout().GetTaggedObject());
47         auto attr = JSHandle<JSTaggedValue>(thread, JSTaggedValue(layoutInfo->GetAttr(last).GetPropertyMetaData()));
48         auto lastKey = JSHandle<JSTaggedValue>(thread, layoutInfo->GetKey(last));
49         auto lastHClass = JSHandle<JSTaggedValue>(thread, cachedHClass);
50         dict.Update(TransitionsDictionary::Create(thread));
51         transitions = TransitionsDictionary::PutIfAbsent(thread, dict, lastKey, lastHClass, attr).GetTaggedValue();
52     }
53     auto attr = JSHandle<JSTaggedValue>(thread, JSTaggedValue(attributes.GetPropertyMetaData()));
54     dict.Update(transitions);
55     transitions =
56         TransitionsDictionary::PutIfAbsent(thread, dict, key, JSHandle<JSTaggedValue>(child), attr).GetTaggedValue();
57     parent->SetTransitions(thread, transitions);
58 }
59 
AddExtensionTransitions(const JSThread * thread,const JSHandle<JSHClass> & parent,const JSHandle<JSHClass> & child,const JSHandle<JSTaggedValue> & key)60 void JSHClass::AddExtensionTransitions(const JSThread *thread, const JSHandle<JSHClass> &parent,
61                                        const JSHandle<JSHClass> &child, const JSHandle<JSTaggedValue> &key)
62 {
63     auto attr = JSHandle<JSTaggedValue>(thread, PropertyAttributes(0).GetTaggedValue());
64     AddProtoTransitions(thread, parent, child, key, attr);
65 }
66 
AddProtoTransitions(const JSThread * thread,const JSHandle<JSHClass> & parent,const JSHandle<JSHClass> & child,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & proto)67 void JSHClass::AddProtoTransitions(const JSThread *thread, const JSHandle<JSHClass> &parent,
68                                    const JSHandle<JSHClass> &child, const JSHandle<JSTaggedValue> &key,
69                                    const JSHandle<JSTaggedValue> &proto)
70 {
71     JSTaggedValue transitions = parent->GetTransitions();
72     JSMutableHandle<TransitionsDictionary> dict(thread, JSTaggedValue::Undefined());
73     if (transitions.IsUndefined()) {
74         transitions = TransitionsDictionary::Create(thread).GetTaggedValue();
75     } else if (transitions.IsWeak()) {
76         auto cachedHClass = JSHClass::Cast(transitions.GetTaggedWeakRef());
77         uint32_t last = cachedHClass->NumberOfProps() - 1;
78         LayoutInfo *layoutInfo = LayoutInfo::Cast(cachedHClass->GetLayout().GetTaggedObject());
79         auto attr = JSHandle<JSTaggedValue>(thread, JSTaggedValue(layoutInfo->GetAttr(last).GetPropertyMetaData()));
80         auto lastKey = JSHandle<JSTaggedValue>(thread, layoutInfo->GetKey(last));
81         auto lastHClass = JSHandle<JSTaggedValue>(thread, cachedHClass);
82         dict.Update(TransitionsDictionary::Create(thread));
83         transitions = TransitionsDictionary::PutIfAbsent(thread, dict, lastKey, lastHClass, attr).GetTaggedValue();
84     }
85 
86     dict.Update(transitions);
87     transitions =
88         TransitionsDictionary::PutIfAbsent(thread, dict, key, JSHandle<JSTaggedValue>(child), proto).GetTaggedValue();
89     parent->SetTransitions(thread, transitions);
90 }
91 
FindTransitions(const JSTaggedValue & key,const JSTaggedValue & attributes)92 inline JSHClass *JSHClass::FindTransitions(const JSTaggedValue &key, const JSTaggedValue &attributes)
93 {
94     DISALLOW_GARBAGE_COLLECTION;
95     JSTaggedValue transitions = GetTransitions();
96     if (transitions.IsUndefined()) {
97         return nullptr;
98     }
99     if (transitions.IsWeak()) {
100         auto cachedHClass = JSHClass::Cast(transitions.GetTaggedWeakRef());
101         int last = static_cast<int>(cachedHClass->NumberOfProps()) - 1;
102         LayoutInfo *layoutInfo = LayoutInfo::Cast(cachedHClass->GetLayout().GetTaggedObject());
103         auto attr = layoutInfo->GetAttr(last).GetPropertyMetaData();
104         auto cachedKey = layoutInfo->GetKey(last);
105         if (attr == attributes.GetInt() && key == cachedKey) {
106             return cachedHClass;
107         }
108         return nullptr;
109     }
110 
111     ASSERT(transitions.IsTaggedArray());
112     TransitionsDictionary *dict = TransitionsDictionary::Cast(transitions.GetTaggedObject());
113     auto entry = dict->FindEntry(key, attributes);
114     if (entry == -1) {
115         return nullptr;
116     }
117 
118     JSTaggedValue ret = dict->GetValue(entry);
119     if (ret.IsUndefined()) {
120         return nullptr;
121     }
122 
123     return JSHClass::Cast(ret.GetTaggedWeakRef());
124 }
125 
FindProtoTransitions(const JSTaggedValue & key,const JSTaggedValue & proto)126 inline JSHClass *JSHClass::FindProtoTransitions(const JSTaggedValue &key, const JSTaggedValue &proto)
127 {
128     DISALLOW_GARBAGE_COLLECTION;
129     JSTaggedValue transitions = GetTransitions();
130     if (transitions.IsWeak() || !transitions.IsTaggedArray()) {
131         ASSERT(transitions.IsUndefined() || transitions.IsWeak());
132         return nullptr;
133     }
134     ASSERT(transitions.IsTaggedArray());
135     TransitionsDictionary *dict = TransitionsDictionary::Cast(transitions.GetTaggedObject());
136     auto entry = dict->FindEntry(key, proto);
137     if (entry == -1) {
138         return nullptr;
139     }
140 
141     JSTaggedValue ret = dict->GetValue(entry);
142     if (ret.IsUndefined()) {
143         return nullptr;
144     }
145 
146     return JSHClass::Cast(ret.GetTaggedWeakRef());
147 }
148 
UpdatePropertyMetaData(const JSThread * thread,const JSTaggedValue & key,const PropertyAttributes & metaData)149 inline void JSHClass::UpdatePropertyMetaData(const JSThread *thread, [[maybe_unused]] const JSTaggedValue &key,
150                                              const PropertyAttributes &metaData)
151 {
152     DISALLOW_GARBAGE_COLLECTION;
153     ASSERT(!GetLayout().IsNull());
154     LayoutInfo *layoutInfo = LayoutInfo::Cast(GetLayout().GetTaggedObject());
155     ASSERT(layoutInfo->GetLength() != 0);
156     uint32_t entry = metaData.GetOffset();
157 
158     layoutInfo->SetNormalAttr(thread, entry, metaData);
159 }
160 
HasReferenceField()161 inline bool JSHClass::HasReferenceField()
162 {
163     auto type = GetObjectType();
164     switch (type) {
165         case JSType::LINE_STRING:
166         case JSType::CONSTANT_STRING:
167         case JSType::JS_NATIVE_POINTER:
168             return false;
169         default:
170             return true;
171     }
172 }
173 
SizeFromJSHClass(TaggedObject * header)174 inline size_t JSHClass::SizeFromJSHClass(TaggedObject *header)
175 {
176     // CAUTION! Never use T::Cast(header) in this function
177     // it would cause issue during GC because hclass may forward to a new addres
178     // and the casting method would still use the old address.
179     auto type = GetObjectType();
180     size_t size = 0;
181     switch (type) {
182         case JSType::TAGGED_ARRAY:
183         case JSType::TAGGED_DICTIONARY:
184         case JSType::LEXICAL_ENV:
185         case JSType::CONSTANT_POOL:
186         case JSType::AOT_LITERAL_INFO:
187         case JSType::VTABLE:
188         case JSType::COW_TAGGED_ARRAY:
189             size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(),
190                 reinterpret_cast<TaggedArray *>(header)->GetLength());
191             break;
192         case JSType::BYTE_ARRAY:
193             size = ByteArray::ComputeSize(reinterpret_cast<ByteArray *>(header)->GetByteLength(),
194                                           reinterpret_cast<ByteArray *>(header)->GetArrayLength());
195             size = AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT));
196             break;
197         case JSType::LINE_STRING:
198             size = LineEcmaString::ObjectSize(reinterpret_cast<EcmaString* >(header));
199             size = AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT));
200             break;
201         case JSType::CONSTANT_STRING:
202             size = ConstantString::SIZE;
203             size = AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT));
204             break;
205         case JSType::TREE_STRING:
206             size = TreeEcmaString::SIZE;
207             size = AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT));
208             break;
209         case JSType::MACHINE_CODE_OBJECT:
210             size = reinterpret_cast<MachineCode *>(header)->GetMachineCodeObjectSize();
211             size = AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT));
212             break;
213         case JSType::BIGINT:
214             size = BigInt::ComputeSize(reinterpret_cast<BigInt *>(header)->GetLength());
215             size = AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT));
216             break;
217         default:
218             ASSERT(GetObjectSize() != 0);
219             size = GetObjectSize();
220             break;
221     }
222     ASSERT(AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)) == size);
223     return size;
224 }
225 
Copy(const JSThread * thread,const JSHClass * jshclass)226 inline void JSHClass::Copy(const JSThread *thread, const JSHClass *jshclass)
227 {
228     DISALLOW_GARBAGE_COLLECTION;
229 
230     // copy jshclass
231     SetPrototype(thread, jshclass->GetPrototype());
232     SetBitField(jshclass->GetBitField());
233     SetIsAllTaggedProp(jshclass->IsAllTaggedProp());
234     SetNumberOfProps(jshclass->NumberOfProps());
235 }
236 
FindPropertyEntry(const JSThread * thread,JSHClass * hclass,JSTaggedValue key)237 inline int JSHClass::FindPropertyEntry(const JSThread *thread, JSHClass *hclass, JSTaggedValue key)
238 {
239     DISALLOW_GARBAGE_COLLECTION;
240     LayoutInfo *layout = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject());
241     uint32_t propsNumber = hclass->NumberOfProps();
242     int entry = layout->FindElementWithCache(thread, hclass, key, propsNumber);
243     return entry;
244 }
245 }  // namespace panda::ecmascript
246 
247 #endif  // ECMASCRIPT_JS_HCLASS_INL_H
248