• 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/transitions_dictionary.h"
23 #include "ecmascript/mem/assert_scope.h"
24 
25 namespace panda::ecmascript {
Cast(const TaggedObject * object)26 inline JSHClass *JSHClass::Cast(const TaggedObject *object)
27 {
28     ASSERT(JSTaggedValue(object).IsJSHClass());
29     return static_cast<JSHClass *>(const_cast<TaggedObject *>(object));
30 }
31 
AddTransitions(const JSThread * thread,const JSHandle<JSHClass> & parent,const JSHandle<JSHClass> & child,const JSHandle<JSTaggedValue> & key,PropertyAttributes attributes)32 void JSHClass::AddTransitions(const JSThread *thread, const JSHandle<JSHClass> &parent, const JSHandle<JSHClass> &child,
33                               const JSHandle<JSTaggedValue> &key, PropertyAttributes attributes)
34 {
35     JSTaggedValue transitions = parent->GetTransitions();
36     if (transitions.IsUndefined()) {
37         JSTaggedValue weakChild = JSTaggedValue(child.GetTaggedValue().CreateAndGetWeakRef());
38         parent->SetTransitions(thread, weakChild);
39         return;
40     }
41     JSMutableHandle<TransitionsDictionary> dict(thread, JSTaggedValue::Undefined());
42     if (transitions.IsWeak()) {
43         auto cachedHClass = JSHClass::Cast(transitions.GetTaggedWeakRef());
44         int last = cachedHClass->NumberOfProps() - 1;
45         LayoutInfo *layoutInfo = LayoutInfo::Cast(cachedHClass->GetLayout().GetTaggedObject());
46         auto attr = JSHandle<JSTaggedValue>(thread, JSTaggedValue(layoutInfo->GetAttr(last).GetPropertyMetaData()));
47         auto lastKey = JSHandle<JSTaggedValue>(thread, layoutInfo->GetKey(last));
48         auto lastHClass = JSHandle<JSTaggedValue>(thread, cachedHClass);
49         dict.Update(TransitionsDictionary::Create(thread));
50         transitions = TransitionsDictionary::PutIfAbsent(thread, dict, lastKey, lastHClass, attr).GetTaggedValue();
51     }
52     auto attr = JSHandle<JSTaggedValue>(thread, JSTaggedValue(attributes.GetPropertyMetaData()));
53     dict.Update(transitions);
54     transitions =
55         TransitionsDictionary::PutIfAbsent(thread, dict, key, JSHandle<JSTaggedValue>(child), attr).GetTaggedValue();
56     parent->SetTransitions(thread, transitions);
57 }
58 
AddExtensionTransitions(const JSThread * thread,const JSHandle<JSHClass> & parent,const JSHandle<JSHClass> & child,const JSHandle<JSTaggedValue> & key)59 void JSHClass::AddExtensionTransitions(const JSThread *thread, const JSHandle<JSHClass> &parent,
60                                        const JSHandle<JSHClass> &child, const JSHandle<JSTaggedValue> &key)
61 {
62     auto attr = JSHandle<JSTaggedValue>(thread, PropertyAttributes(0).GetTaggedValue());
63     AddProtoTransitions(thread, parent, child, key, attr);
64 }
65 
AddProtoTransitions(const JSThread * thread,const JSHandle<JSHClass> & parent,const JSHandle<JSHClass> & child,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & proto)66 void JSHClass::AddProtoTransitions(const JSThread *thread, const JSHandle<JSHClass> &parent,
67                                    const JSHandle<JSHClass> &child, const JSHandle<JSTaggedValue> &key,
68                                    const JSHandle<JSTaggedValue> &proto)
69 {
70     JSTaggedValue transitions = parent->GetTransitions();
71     JSMutableHandle<TransitionsDictionary> dict(thread, JSTaggedValue::Undefined());
72     if (transitions.IsUndefined()) {
73         transitions = TransitionsDictionary::Create(thread).GetTaggedValue();
74     } else if (transitions.IsWeak()) {
75         auto cachedHClass = JSHClass::Cast(transitions.GetTaggedWeakRef());
76         int last = cachedHClass->NumberOfProps() - 1;
77         LayoutInfo *layoutInfo = LayoutInfo::Cast(cachedHClass->GetLayout().GetTaggedObject());
78         auto attr = JSHandle<JSTaggedValue>(thread, JSTaggedValue(layoutInfo->GetAttr(last).GetPropertyMetaData()));
79         auto lastKey = JSHandle<JSTaggedValue>(thread, layoutInfo->GetKey(last));
80         auto lastHClass = JSHandle<JSTaggedValue>(thread, cachedHClass);
81         dict.Update(TransitionsDictionary::Create(thread));
82         transitions = TransitionsDictionary::PutIfAbsent(thread, dict, lastKey, lastHClass, attr).GetTaggedValue();
83     }
84 
85     dict.Update(transitions);
86     transitions =
87         TransitionsDictionary::PutIfAbsent(thread, dict, key, JSHandle<JSTaggedValue>(child), proto).GetTaggedValue();
88     parent->SetTransitions(thread, transitions);
89 }
90 
FindTransitions(const JSTaggedValue & key,const JSTaggedValue & attributes)91 inline JSHClass *JSHClass::FindTransitions(const JSTaggedValue &key, const JSTaggedValue &attributes)
92 {
93     DISALLOW_GARBAGE_COLLECTION;
94     JSTaggedValue transitions = GetTransitions();
95     if (transitions.IsUndefined()) {
96         return nullptr;
97     }
98     if (transitions.IsWeak()) {
99         auto cachedHClass = JSHClass::Cast(transitions.GetTaggedWeakRef());
100         int last = cachedHClass->NumberOfProps() - 1;
101         LayoutInfo *layoutInfo = LayoutInfo::Cast(cachedHClass->GetLayout().GetTaggedObject());
102         auto attr = layoutInfo->GetAttr(last).GetPropertyMetaData();
103         auto cachedKey = layoutInfo->GetKey(last);
104         if (attr == attributes.GetInt() && key == cachedKey) {
105             return cachedHClass;
106         }
107         return nullptr;
108     }
109 
110     ASSERT(transitions.IsTaggedArray());
111     TransitionsDictionary *dict = TransitionsDictionary::Cast(transitions.GetTaggedObject());
112     auto entry = dict->FindEntry(key, attributes);
113     if (entry == -1) {
114         return nullptr;
115     }
116 
117     JSTaggedValue ret = dict->GetValue(entry);
118     if (ret.IsUndefined()) {
119         return nullptr;
120     }
121 
122     return JSHClass::Cast(ret.GetTaggedWeakRef());
123 }
124 
FindProtoTransitions(const JSTaggedValue & key,const JSTaggedValue & proto)125 inline JSHClass *JSHClass::FindProtoTransitions(const JSTaggedValue &key, const JSTaggedValue &proto)
126 {
127     DISALLOW_GARBAGE_COLLECTION;
128     JSTaggedValue transitions = GetTransitions();
129     if (transitions.IsWeak() || !transitions.IsTaggedArray()) {
130         ASSERT(transitions.IsUndefined() || transitions.IsWeak());
131         return nullptr;
132     }
133     ASSERT(transitions.IsTaggedArray());
134     TransitionsDictionary *dict = TransitionsDictionary::Cast(transitions.GetTaggedObject());
135     auto entry = dict->FindEntry(key, proto);
136     if (entry == -1) {
137         return nullptr;
138     }
139 
140     JSTaggedValue ret = dict->GetValue(entry);
141     if (ret.IsUndefined()) {
142         return nullptr;
143     }
144 
145     return JSHClass::Cast(ret.GetTaggedWeakRef());
146 }
147 
UpdatePropertyMetaData(const JSThread * thread,const JSTaggedValue & key,const PropertyAttributes & metaData)148 inline void JSHClass::UpdatePropertyMetaData(const JSThread *thread, [[maybe_unused]] const JSTaggedValue &key,
149                                              const PropertyAttributes &metaData)
150 {
151     DISALLOW_GARBAGE_COLLECTION;
152     ASSERT(!GetLayout().IsNull());
153     LayoutInfo *layoutInfo = LayoutInfo::Cast(GetLayout().GetTaggedObject());
154     ASSERT(layoutInfo->GetLength() != 0);
155     int entry = metaData.GetOffset();
156 
157     layoutInfo->SetNormalAttr(thread, entry, metaData);
158 }
159 
HasReferenceField()160 inline bool JSHClass::HasReferenceField()
161 {
162     auto type = GetObjectType();
163     switch (type) {
164         case JSType::STRING:
165         case JSType::JS_NATIVE_POINTER:
166             return false;
167         default:
168             return true;
169     }
170 }
171 
SizeFromJSHClass(TaggedObject * header)172 inline size_t JSHClass::SizeFromJSHClass(TaggedObject *header)
173 {
174     auto type = GetObjectType();
175     size_t size = 0;
176     switch (type) {
177         case JSType::TAGGED_ARRAY:
178         case JSType::TAGGED_DICTIONARY:
179             size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(),
180                 reinterpret_cast<TaggedArray *>(header)->GetLength());
181             break;
182         case JSType::STRING:
183             size = reinterpret_cast<EcmaString *>(header)->ObjectSize();
184             size = AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT));
185             break;
186         case JSType::MACHINE_CODE_OBJECT:
187             size = reinterpret_cast<MachineCode *>(header)->GetMachineCodeObjectSize();
188             size = AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT));
189             break;
190         default:
191             ASSERT(GetObjectSize() != 0);
192             size = GetObjectSize();
193             break;
194     }
195     ASSERT(AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)) == size);
196     return size;
197 }
198 
Copy(const JSThread * thread,const JSHClass * jshcalss)199 inline void JSHClass::Copy(const JSThread *thread, const JSHClass *jshcalss)
200 {
201     DISALLOW_GARBAGE_COLLECTION;
202 
203     // copy jshclass
204     SetPrototype(thread, jshcalss->GetPrototype());
205     SetBitField(jshcalss->GetBitField());
206     SetNumberOfProps(jshcalss->NumberOfProps());
207 }
208 }  // namespace panda::ecmascript
209 
210 #endif  // ECMASCRIPT_JS_HCLASS_INL_H
211