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