• 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/js_object-inl.h"
17 #include "pgo_profiler/pgo_profiler_layout.h"
18 
19 namespace panda::ecmascript {
20 using PGOHandler = pgo::PGOHandler;
Initialize(const JSThread * thread,int num)21 void LayoutInfo::Initialize(const JSThread *thread, int num)
22 {
23     SetExtraLength(num);
24     int propNum = GetPropertiesCapacity();
25     auto attr = PropertyAttributes();
26     for (int i = 0; i < propNum; i++) {
27         SetPropertyInit(thread, i, JSTaggedValue::Hole(), attr);
28     }
29 }
30 
GetAllKeys(const JSThread * thread,int end,int offset,TaggedArray * keyArray)31 void LayoutInfo::GetAllKeys(const JSThread *thread, int end, int offset, TaggedArray *keyArray)
32 {
33     ASSERT(end <= NumberOfElements());
34     ASSERT_PRINT(offset + end <= static_cast<int>(keyArray->GetLength()),
35                  "keyArray capacity is not enough for dictionary");
36 
37     DISALLOW_GARBAGE_COLLECTION;
38     int enumKeys = 0;
39     for (int i = 0; i < end; i++) {
40         JSTaggedValue key = GetKey(i);
41         if (key.IsString()) {
42             keyArray->Set(thread, enumKeys + offset, key);
43             enumKeys++;
44         }
45     }
46 
47     if (enumKeys < end) {
48         for (int i = 0; i < end; i++) {
49             JSTaggedValue key = GetKey(i);
50             if (key.IsSymbol()) {
51                 keyArray->Set(thread, enumKeys + offset, key);
52                 enumKeys++;
53             }
54         }
55     }
56 }
GetAllKeysByFilter(const JSThread * thread,uint32_t numberOfProps,uint32_t & keyArrayEffectivelength,TaggedArray * keyArray,uint32_t filter)57 void LayoutInfo::GetAllKeysByFilter(const JSThread *thread, uint32_t numberOfProps, uint32_t &keyArrayEffectivelength,
58                                     TaggedArray *keyArray, uint32_t filter)
59 {
60     ASSERT(numberOfProps <= static_cast<uint32_t>(NumberOfElements()));
61     ASSERT_PRINT(keyArrayEffectivelength + numberOfProps <= keyArray->GetLength(),
62                  "keyArray capacity is not enough for dictionary");
63 
64     DISALLOW_GARBAGE_COLLECTION;
65     uint32_t enumKeys = 0;
66     for (uint32_t i = 0; i < numberOfProps; i++) {
67         JSTaggedValue key = GetKey(static_cast<int>(i));
68         if (key.IsString() && !(filter & NATIVE_KEY_SKIP_STRINGS)) {
69             PropertyAttributes attr = GetAttr(static_cast<int>(i));
70             bool bIgnore = FilterHelper::IgnoreKeyByFilter<PropertyAttributes>(attr, filter);
71             if (bIgnore) {
72                 continue;
73             }
74             keyArray->Set(thread, keyArrayEffectivelength, key);
75             keyArrayEffectivelength++;
76             enumKeys++;
77         }
78     }
79 
80     if (enumKeys < numberOfProps) {
81         for (uint32_t i = 0; i < numberOfProps; i++) {
82             JSTaggedValue key = GetKey(static_cast<int>(i));
83             if (key.IsSymbol() && !(filter & NATIVE_KEY_SKIP_SYMBOLS)) {
84                 PropertyAttributes attr = GetAttr(static_cast<int>(i));
85                 bool bIgnore = FilterHelper::IgnoreKeyByFilter<PropertyAttributes>(attr, filter);
86                 if (bIgnore) {
87                     continue;
88                 }
89                 keyArray->Set(thread, keyArrayEffectivelength, key);
90                 keyArrayEffectivelength++;
91             }
92         }
93     }
94 }
95 
GetAllKeysForSerialization(int end,std::vector<JSTaggedValue> & keyVector)96 void LayoutInfo::GetAllKeysForSerialization(int end, std::vector<JSTaggedValue> &keyVector)
97 {
98     ASSERT(end <= NumberOfElements());
99     for (int i = 0; i < end; i++) {
100         JSTaggedValue key = GetKey(i);
101         if (key.IsString() || key.IsSymbol()) {
102             keyVector.emplace_back(key);
103         }
104     }
105 }
106 
GetNumOfEnumKeys(int end) const107 std::pair<uint32_t, uint32_t> LayoutInfo::GetNumOfEnumKeys(int end) const
108 {
109     ASSERT(end <= NumberOfElements());
110     uint32_t enumKeys = 0;
111     uint32_t shadowKeys = 0;
112     for (int i = 0; i < end; i++) {
113         JSTaggedValue key = GetKey(i);
114         if (!key.IsString()) {
115             continue;
116         }
117         if (GetAttr(i).IsEnumerable()) {
118             enumKeys++;
119         } else {
120             shadowKeys++;
121         }
122     }
123     return std::make_pair(enumKeys, shadowKeys);
124 }
125 
GetAllEnumKeys(JSThread * thread,int end,int offset,JSHandle<TaggedArray> keyArray,uint32_t * keys,JSHandle<TaggedQueue> shadowQueue,int32_t lastLength)126 void LayoutInfo::GetAllEnumKeys(JSThread *thread, int end, int offset, JSHandle<TaggedArray> keyArray,
127                                 uint32_t *keys, JSHandle<TaggedQueue> shadowQueue, int32_t lastLength)
128 {
129     ASSERT(end <= NumberOfElements());
130     ASSERT_PRINT(offset <= static_cast<int>(keyArray->GetLength()),
131                  "keyArray capacity is not enough for dictionary");
132     JSMutableHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue::Undefined());
133     int enumKeys = 0;
134     for (int i = 0; i < end; i++) {
135         keyHandle.Update(GetKey(i));
136         if (!keyHandle->IsString()) {
137             continue;
138         }
139         if (GetAttr(i).IsEnumerable()) {
140             bool isDuplicated = JSObject::IsDepulicateKeys(thread, keyArray, lastLength, shadowQueue, keyHandle);
141             if (isDuplicated) {
142                 continue;
143             }
144             keyArray->Set(thread, enumKeys + offset, keyHandle);
145             enumKeys++;
146         } else {
147             TaggedQueue::PushFixedQueue(thread, shadowQueue, keyHandle);
148         }
149     }
150     *keys += enumKeys;
151 }
152 
GetAllEnumKeys(JSThread * thread,int end,int offset,JSHandle<TaggedArray> keyArray,uint32_t * keys)153 void LayoutInfo::GetAllEnumKeys(JSThread *thread, int end, int offset, JSHandle<TaggedArray> keyArray, uint32_t *keys)
154 {
155     ASSERT(end <= NumberOfElements());
156     ASSERT_PRINT(offset <= static_cast<int>(keyArray->GetLength()),
157                  "keyArray capacity is not enough for dictionary");
158     JSMutableHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue::Undefined());
159     int enumKeys = 0;
160     for (int i = 0; i < end; i++) {
161         keyHandle.Update(GetKey(i));
162         if (keyHandle->IsString() && GetAttr(i).IsEnumerable()) {
163             keyArray->Set(thread, enumKeys + offset, keyHandle);
164             enumKeys++;
165         }
166     }
167     *keys += enumKeys;
168 }
169 
GetSymbolKeyString(JSTaggedValue key)170 CString LayoutInfo::GetSymbolKeyString(JSTaggedValue key)
171 {
172     auto symbol = JSSymbol::Cast(key);
173     if (!symbol->HasId()) {
174         return "";
175     }
176     auto id = symbol->GetPrivateId();
177     auto symbolDesc = symbol->GetDescription();
178     if (symbolDesc.IsUndefined()) {
179         return ToCString(id);
180     }
181     if (!symbolDesc.IsString()) {
182         return "";
183     }
184     CString str = EcmaStringAccessor(symbolDesc).ToCString();
185     if (str != "method") {
186         return "";
187     }
188     return str.append("_").append(ToCString(id));
189 }
190 
DumpFieldIndexByPGO(int index,pgo::HClassLayoutDesc * desc)191 void LayoutInfo::DumpFieldIndexByPGO(int index, pgo::HClassLayoutDesc* desc)
192 {
193     auto key = GetKey(index);
194     auto attr = GetAttr(index);
195     SetIsPGODumped(index);
196     TrackType type = attr.GetTrackType();
197     int propertyMeta = attr.GetPropertyMetaData();
198     if (key.IsString()) {
199         auto keyString = EcmaStringAccessor(key).ToCString();
200         desc->InsertKeyAndDesc(keyString, PGOHandler(type, propertyMeta, false));
201     } else if (key.IsSymbol()) {
202         auto keyString = GetSymbolKeyString(key);
203         if (keyString.empty()) {
204             return;
205         }
206         desc->InsertKeyAndDesc(keyString, PGOHandler(type, propertyMeta, true));
207     }
208 }
209 
UpdateFieldIndexByPGO(int index,pgo::HClassLayoutDesc * desc)210 bool LayoutInfo::UpdateFieldIndexByPGO(int index, pgo::HClassLayoutDesc* desc)
211 {
212     auto key = GetKey(index);
213     auto attr = GetAttr(index);
214     if (attr.IsPGODumped()) {
215         return true;
216     }
217     SetIsPGODumped(index);
218     TrackType type = attr.GetTrackType();
219     int propertyMeta = attr.GetPropertyMetaData();
220     if (key.IsString()) {
221         auto keyString = EcmaStringAccessor(key).ToCString();
222         return desc->UpdateKeyAndDesc(keyString, PGOHandler(type, propertyMeta, false));
223     } else if (key.IsSymbol()) {
224         auto keyString = GetSymbolKeyString(key);
225         if (keyString.empty()) {
226             return false;
227         }
228         return desc->UpdateKeyAndDesc(keyString, PGOHandler(type, propertyMeta, true));
229     }
230     return false;
231 }
232 }  // namespace panda::ecmascript
233