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