• 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/js_object-inl.h"
20 #include "ecmascript/js_symbol.h"
21 #include "ecmascript/mem/assert_scope.h"
22 
23 namespace panda::ecmascript {
AddKey(const JSThread * thread,int index,const JSTaggedValue & key,const PropertyAttributes & attr)24 void LayoutInfo::AddKey(const JSThread *thread, [[maybe_unused]] int index, const JSTaggedValue &key,
25                         const PropertyAttributes &attr)
26 {
27     DISALLOW_GARBAGE_COLLECTION;
28     int number = NumberOfElements();
29     ASSERT(attr.GetOffset() == static_cast<uint32_t>(number));
30     ASSERT(number + 1 <= GetPropertiesCapacity());
31     ASSERT(number == index);
32     SetNumberOfElements(thread, number + 1);
33     SetPropertyInit(thread, number, key, attr);
34 
35     uint32_t keyHash = key.GetKeyHashCode();
36     int insertIndex = number;
37     for (; insertIndex > 0; --insertIndex) {
38         JSTaggedValue prevKey = GetSortedKey(insertIndex - 1);
39         if (prevKey.GetKeyHashCode() <= keyHash) {
40             break;
41         }
42         SetSortedIndex(thread, insertIndex, GetSortedIndex(insertIndex - 1));
43     }
44     SetSortedIndex(thread, insertIndex, number);
45 }
46 
GetAllKeys(const JSThread * thread,int end,int offset,TaggedArray * keyArray,const JSHandle<JSObject> object)47 void LayoutInfo::GetAllKeys(const JSThread *thread, int end, int offset, TaggedArray *keyArray,
48                             const JSHandle<JSObject> object)
49 {
50     ASSERT(end <= NumberOfElements());
51     ASSERT_PRINT(offset + end <= static_cast<int>(keyArray->GetLength()),
52                  "keyArray capacity is not enough for dictionary");
53 
54     DISALLOW_GARBAGE_COLLECTION;
55     int enumKeys = 0;
56     for (int i = 0; i < end; i++) {
57         JSTaggedValue key = GetKey(i);
58         if (key.IsString()) {
59             if (IsUninitializedProperty(object, i)) {
60                 continue;
61             }
62             keyArray->Set(thread, enumKeys + offset, key);
63             enumKeys++;
64         }
65     }
66 
67     if (enumKeys < end) {
68         for (int i = 0; i < end; i++) {
69             JSTaggedValue key = GetKey(i);
70             if (key.IsSymbol()) {
71                 keyArray->Set(thread, enumKeys + offset, key);
72                 enumKeys++;
73             }
74         }
75     }
76 }
77 
GetAllKeys(int end,std::vector<JSTaggedValue> & keyVector,const JSHandle<JSObject> object)78 void LayoutInfo::GetAllKeys(int end, std::vector<JSTaggedValue> &keyVector, const JSHandle<JSObject> object)
79 {
80     ASSERT(end <= NumberOfElements());
81     for (int i = 0; i < end; i++) {
82         JSTaggedValue key = GetKey(i);
83         if (key.IsString() || key.IsSymbol()) {
84             if (IsUninitializedProperty(object, i)) {
85                 continue;
86             }
87             keyVector.emplace_back(key);
88         }
89     }
90 }
91 
GetAllEnumKeys(const JSThread * thread,int end,int offset,TaggedArray * keyArray,uint32_t * keys,const JSHandle<JSObject> object)92 void LayoutInfo::GetAllEnumKeys(const JSThread *thread, int end, int offset, TaggedArray *keyArray,
93                                 uint32_t *keys, const JSHandle<JSObject> object)
94 {
95     ASSERT(end <= NumberOfElements());
96     ASSERT_PRINT(offset + end <= static_cast<int>(keyArray->GetLength()),
97                  "keyArray capacity is not enough for dictionary");
98 
99     DISALLOW_GARBAGE_COLLECTION;
100     int enumKeys = 0;
101     for (int i = 0; i < end; i++) {
102         JSTaggedValue key = GetKey(i);
103         if (key.IsString() && GetAttr(i).IsEnumerable()) {
104             if (IsUninitializedProperty(object, i)) {
105                 continue;
106             }
107             keyArray->Set(thread, enumKeys + offset, key);
108             enumKeys++;
109         }
110     }
111     *keys += enumKeys;
112 }
113 
IsUninitializedProperty(const JSHandle<JSObject> object,uint32_t index)114 bool LayoutInfo::IsUninitializedProperty(const JSHandle<JSObject> object, uint32_t index)
115 {
116     PropertyAttributes attr = GetAttr(index);
117     if (!attr.IsInlinedProps()) {
118         return false;
119     }
120 
121     JSTaggedValue val = object->GetPropertyInlinedProps(attr.GetOffset());
122     return val.IsHole();
123 }
124 }  // namespace panda::ecmascript
125