• 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 #include "ecmascript/layout_info-inl.h"
17 
18 #include "ecmascript/ecma_string.h"
19 #include "ecmascript/filter_helper.h"
20 #include "ecmascript/js_object-inl.h"
21 #include "ecmascript/js_symbol.h"
22 #include "ecmascript/mem/assert_scope.h"
23 
24 namespace panda::ecmascript {
Initialize(const JSThread * thread,int num)25 void LayoutInfo::Initialize(const JSThread *thread, int num)
26 {
27     SetExtraLength(num);
28     int propNum = GetPropertiesCapacity();
29     auto attr = PropertyAttributes();
30     for (int i = 0; i < propNum; i++) {
31         SetPropertyInit(thread, i, JSTaggedValue::Hole(), attr);
32     }
33 }
34 
AddKey(const JSThread * thread,int index,const JSTaggedValue & key,const PropertyAttributes & attr)35 void LayoutInfo::AddKey(const JSThread *thread, [[maybe_unused]] int index, const JSTaggedValue &key,
36                         const PropertyAttributes &attr)
37 {
38     DISALLOW_GARBAGE_COLLECTION;
39     int number = NumberOfElements();
40     ASSERT(attr.GetOffset() == static_cast<uint32_t>(number));
41     ASSERT(number + 1 <= GetPropertiesCapacity());
42     ASSERT(number == index);
43     SetNumberOfElements(thread, number + 1);
44     SetPropertyInit(thread, number, key, attr);
45 
46     uint32_t keyHash = key.GetKeyHashCode();
47     int insertIndex = number;
48     for (; insertIndex > 0; --insertIndex) {
49         JSTaggedValue prevKey = GetSortedKey(insertIndex - 1);
50         if (prevKey.GetKeyHashCode() <= keyHash) {
51             break;
52         }
53         SetSortedIndex(thread, insertIndex, GetSortedIndex(insertIndex - 1));
54     }
55     SetSortedIndex(thread, insertIndex, number);
56 }
57 
GetAllKeys(const JSThread * thread,int end,int offset,TaggedArray * keyArray,const JSHandle<JSObject> object)58 void LayoutInfo::GetAllKeys(const JSThread *thread, int end, int offset, TaggedArray *keyArray,
59                             const JSHandle<JSObject> object)
60 {
61     ASSERT(end <= NumberOfElements());
62     ASSERT_PRINT(offset + end <= static_cast<int>(keyArray->GetLength()),
63                  "keyArray capacity is not enough for dictionary");
64 
65     DISALLOW_GARBAGE_COLLECTION;
66     int enumKeys = 0;
67     for (int i = 0; i < end; i++) {
68         JSTaggedValue key = GetKey(i);
69         if (key.IsString()) {
70             if (IsUninitializedProperty(object, i)) {
71                 continue;
72             }
73             keyArray->Set(thread, enumKeys + offset, key);
74             enumKeys++;
75         }
76     }
77 
78     if (enumKeys < end) {
79         for (int i = 0; i < end; i++) {
80             JSTaggedValue key = GetKey(i);
81             if (key.IsSymbol()) {
82                 keyArray->Set(thread, enumKeys + offset, key);
83                 enumKeys++;
84             }
85         }
86     }
87 }
GetAllKeysByFilter(const JSThread * thread,uint32_t numberOfProps,uint32_t & keyArrayEffectivelength,TaggedArray * keyArray,const JSHandle<JSObject> object,uint32_t filter)88 void LayoutInfo::GetAllKeysByFilter(const JSThread *thread, uint32_t numberOfProps, uint32_t &keyArrayEffectivelength,
89                                     TaggedArray *keyArray, const JSHandle<JSObject> object, uint32_t filter)
90 {
91     ASSERT(numberOfProps <= static_cast<uint32_t>(NumberOfElements()));
92     ASSERT_PRINT(keyArrayEffectivelength + numberOfProps <= keyArray->GetLength(),
93                  "keyArray capacity is not enough for dictionary");
94 
95     DISALLOW_GARBAGE_COLLECTION;
96     uint32_t enumKeys = 0;
97     for (uint32_t i = 0; i < numberOfProps; i++) {
98         JSTaggedValue key = GetKey(static_cast<int>(i));
99         if (key.IsString() && !(filter & NATIVE_KEY_SKIP_STRINGS)) {
100             if (IsUninitializedProperty(object, i)) {
101                 continue;
102             }
103             PropertyAttributes attr = GetAttr(static_cast<int>(i));
104             bool bIgnore = FilterHelper::IgnoreKeyByFilter<PropertyAttributes>(attr, filter);
105             if (bIgnore) {
106                 continue;
107             }
108             keyArray->Set(thread, keyArrayEffectivelength, key);
109             keyArrayEffectivelength++;
110             enumKeys++;
111         }
112     }
113 
114     if (enumKeys < numberOfProps) {
115         for (uint32_t i = 0; i < numberOfProps; i++) {
116             JSTaggedValue key = GetKey(static_cast<int>(i));
117             if (key.IsSymbol() && !(filter & NATIVE_KEY_SKIP_SYMBOLS)) {
118                 PropertyAttributes attr = GetAttr(static_cast<int>(i));
119                 bool bIgnore = FilterHelper::IgnoreKeyByFilter<PropertyAttributes>(attr, filter);
120                 if (bIgnore) {
121                     continue;
122                 }
123                 keyArray->Set(thread, keyArrayEffectivelength, key);
124                 keyArrayEffectivelength++;
125             }
126         }
127     }
128 }
129 
GetAllKeys(int end,std::vector<JSTaggedValue> & keyVector,const JSHandle<JSObject> object)130 void LayoutInfo::GetAllKeys(int end, std::vector<JSTaggedValue> &keyVector, const JSHandle<JSObject> object)
131 {
132     ASSERT(end <= NumberOfElements());
133     for (int i = 0; i < end; i++) {
134         JSTaggedValue key = GetKey(i);
135         if (key.IsString() || key.IsSymbol()) {
136             if (IsUninitializedProperty(object, i)) {
137                 continue;
138             }
139             keyVector.emplace_back(key);
140         }
141     }
142 }
143 
GetAllEnumKeys(const JSThread * thread,int end,int offset,TaggedArray * keyArray,uint32_t * keys,const JSHandle<JSObject> object)144 void LayoutInfo::GetAllEnumKeys(const JSThread *thread, int end, int offset, TaggedArray *keyArray,
145                                 uint32_t *keys, const JSHandle<JSObject> object)
146 {
147     ASSERT(end <= NumberOfElements());
148     ASSERT_PRINT(offset + end <= static_cast<int>(keyArray->GetLength()),
149                  "keyArray capacity is not enough for dictionary");
150 
151     DISALLOW_GARBAGE_COLLECTION;
152     int enumKeys = 0;
153     for (int i = 0; i < end; i++) {
154         JSTaggedValue key = GetKey(i);
155         if (key.IsString() && GetAttr(i).IsEnumerable()) {
156             if (IsUninitializedProperty(object, i)) {
157                 continue;
158             }
159             keyArray->Set(thread, enumKeys + offset, key);
160             enumKeys++;
161         }
162     }
163     *keys += enumKeys;
164 }
165 
IsUninitializedProperty(const JSHandle<JSObject> object,uint32_t index)166 bool LayoutInfo::IsUninitializedProperty(const JSHandle<JSObject> object, uint32_t index)
167 {
168     PropertyAttributes attr = GetAttr(index);
169     if (!attr.IsInlinedProps()) {
170         return false;
171     }
172 
173     JSTaggedValue val = object->GetPropertyInlinedProps(attr.GetOffset());
174     return val.IsHole();
175 }
176 
DumpFieldIndexForProfile(int index,PGOHClassLayoutDesc & desc,PGOObjKind kind)177 void LayoutInfo::DumpFieldIndexForProfile(int index, PGOHClassLayoutDesc &desc, PGOObjKind kind)
178 {
179     auto key = GetKey(index);
180     if (key.IsString()) {
181         auto attr = GetAttr(index);
182         TrackType type = attr.GetTrackType();
183         bool isAccessor = attr.IsAccessor();
184         auto keyString = EcmaStringAccessor(key).ToCString();
185         desc.UpdateKeyAndDesc(keyString.c_str(), PGOHandler(type, isAccessor), kind);
186     }
187 }
188 }  // namespace panda::ecmascript
189