• 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/ic/profile_type_info.h"
17 
18 #include "ecmascript/ic/ic_handler.h"
19 #include "ecmascript/js_function.h"
20 #include "ecmascript/tagged_array-inl.h"
21 
22 namespace panda::ecmascript {
AddElementHandler(JSHandle<JSTaggedValue> hclass,JSHandle<JSTaggedValue> handler) const23 void ProfileTypeAccessor::AddElementHandler(JSHandle<JSTaggedValue> hclass, JSHandle<JSTaggedValue> handler) const
24 {
25     auto profileData = profileTypeInfo_->Get(slotId_);
26     ASSERT(!profileData.IsHole());
27     auto index = slotId_;
28     if (profileData.IsUndefined()) {
29         profileTypeInfo_->Set(thread_, index, GetWeakRef(hclass.GetTaggedValue()));
30         profileTypeInfo_->Set(thread_, index + 1, handler.GetTaggedValue());
31         return;
32     }
33     // clear key ic
34     if (!profileData.IsWeak() && (profileData.IsString() || profileData.IsSymbol())) {
35         profileTypeInfo_->Set(thread_, index, GetWeakRef(hclass.GetTaggedValue()));
36         profileTypeInfo_->Set(thread_, index + 1, handler.GetTaggedValue());
37         return;
38     }
39     AddHandlerWithoutKey(hclass, handler);
40 }
41 
AddHandlerWithoutKey(JSHandle<JSTaggedValue> hclass,JSHandle<JSTaggedValue> handler) const42 void ProfileTypeAccessor::AddHandlerWithoutKey(JSHandle<JSTaggedValue> hclass, JSHandle<JSTaggedValue> handler) const
43 {
44     auto index = slotId_;
45     if (IsNamedGlobalIC(GetKind())) {
46         profileTypeInfo_->Set(thread_, index, handler.GetTaggedValue());
47         return;
48     }
49     auto profileData = profileTypeInfo_->Get(slotId_);
50     ASSERT(!profileData.IsHole());
51     if (profileData.IsUndefined()) {
52         profileTypeInfo_->Set(thread_, index, GetWeakRef(hclass.GetTaggedValue()));
53         profileTypeInfo_->Set(thread_, index + 1, handler.GetTaggedValue());
54         return;
55     }
56     if (!profileData.IsWeak() && profileData.IsTaggedArray()) {  // POLY
57         ASSERT(profileTypeInfo_->Get(index + 1) == JSTaggedValue::Hole());
58         JSHandle<TaggedArray> arr(thread_, profileData);
59         const uint32_t step = 2;
60         uint32_t newLen = arr->GetLength() + step;
61         if (newLen > CACHE_MAX_LEN) {
62             profileTypeInfo_->Set(thread_, index, JSTaggedValue::Hole());
63             profileTypeInfo_->Set(thread_, index + 1, JSTaggedValue::Hole());
64             return;
65         }
66         auto factory = thread_->GetEcmaVM()->GetFactory();
67         JSHandle<TaggedArray> newArr = factory->NewTaggedArray(newLen);
68         uint32_t i = 0;
69         for (; i < arr->GetLength(); i += step) {
70             newArr->Set(thread_, i, arr->Get(i));
71             newArr->Set(thread_, i + 1, arr->Get(i + 1));
72         }
73         newArr->Set(thread_, i, GetWeakRef(hclass.GetTaggedValue()));
74         newArr->Set(thread_, i + 1, handler.GetTaggedValue());
75         profileTypeInfo_->Set(thread_, index, newArr.GetTaggedValue());
76         profileTypeInfo_->Set(thread_, index + 1, JSTaggedValue::Hole());
77         return;
78     }
79     // MONO to POLY
80     auto factory = thread_->GetEcmaVM()->GetFactory();
81     JSHandle<TaggedArray> newArr = factory->NewTaggedArray(POLY_CASE_NUM);
82     uint32_t arrIndex = 0;
83     newArr->Set(thread_, arrIndex++, profileTypeInfo_->Get(index));
84     newArr->Set(thread_, arrIndex++, profileTypeInfo_->Get(index + 1));
85     newArr->Set(thread_, arrIndex++, GetWeakRef(hclass.GetTaggedValue()));
86     newArr->Set(thread_, arrIndex, handler.GetTaggedValue());
87 
88     profileTypeInfo_->Set(thread_, index, newArr.GetTaggedValue());
89     profileTypeInfo_->Set(thread_, index + 1, JSTaggedValue::Hole());
90 }
91 
AddHandlerWithKey(JSHandle<JSTaggedValue> key,JSHandle<JSTaggedValue> hclass,JSHandle<JSTaggedValue> handler) const92 void ProfileTypeAccessor::AddHandlerWithKey(JSHandle<JSTaggedValue> key, JSHandle<JSTaggedValue> hclass,
93                                             JSHandle<JSTaggedValue> handler) const
94 {
95     if (IsValueGlobalIC(GetKind())) {
96         AddGlobalHandlerKey(key, handler);
97         return;
98     }
99     auto profileData = profileTypeInfo_->Get(slotId_);
100     ASSERT(!profileData.IsHole());
101     auto index = slotId_;
102     if (profileData.IsUndefined()) {
103         ASSERT(profileTypeInfo_->Get(index + 1) == JSTaggedValue::Undefined());
104         profileTypeInfo_->Set(thread_, index, key.GetTaggedValue());
105         const int arrayLength = 2;
106         JSHandle<TaggedArray> newArr = thread_->GetEcmaVM()->GetFactory()->NewTaggedArray(arrayLength);
107         newArr->Set(thread_, 0, GetWeakRef(hclass.GetTaggedValue()));
108         newArr->Set(thread_, 1, handler.GetTaggedValue());
109         profileTypeInfo_->Set(thread_, index + 1, newArr.GetTaggedValue());
110         return;
111     }
112     // for element ic, profileData may hclass or taggedarray
113     if (key.GetTaggedValue() != profileData) {
114         profileTypeInfo_->Set(thread_, index, JSTaggedValue::Hole());
115         profileTypeInfo_->Set(thread_, index + 1, JSTaggedValue::Hole());
116         return;
117     }
118     JSTaggedValue patchValue = profileTypeInfo_->Get(index + 1);
119     ASSERT(patchValue.IsTaggedArray());
120     JSHandle<TaggedArray> arr(thread_, patchValue);
121     const uint32_t step = 2;
122     if (arr->GetLength() > step) {  // POLY
123         uint32_t newLen = arr->GetLength() + step;
124         if (newLen > CACHE_MAX_LEN) {
125             profileTypeInfo_->Set(thread_, index, JSTaggedValue::Hole());
126             profileTypeInfo_->Set(thread_, index + 1, JSTaggedValue::Hole());
127             return;
128         }
129         auto factory = thread_->GetEcmaVM()->GetFactory();
130         JSHandle<TaggedArray> newArr = factory->NewTaggedArray(newLen);
131         newArr->Set(thread_, 0, GetWeakRef(hclass.GetTaggedValue()));
132         newArr->Set(thread_, 1, handler.GetTaggedValue());
133         for (uint32_t i = 0; i < arr->GetLength(); i += step) {
134             newArr->Set(thread_, i + step, arr->Get(i));
135             newArr->Set(thread_, i + step + 1, arr->Get(i + 1));
136         }
137         profileTypeInfo_->Set(thread_, index + 1, newArr.GetTaggedValue());
138         return;
139     }
140     // MONO
141     auto factory = thread_->GetEcmaVM()->GetFactory();
142     JSHandle<TaggedArray> newArr = factory->NewTaggedArray(POLY_CASE_NUM);
143     uint32_t arrIndex = 0;
144     newArr->Set(thread_, arrIndex++, arr->Get(0));
145     newArr->Set(thread_, arrIndex++, arr->Get(1));
146     newArr->Set(thread_, arrIndex++, GetWeakRef(hclass.GetTaggedValue()));
147     newArr->Set(thread_, arrIndex++, handler.GetTaggedValue());
148 
149     profileTypeInfo_->Set(thread_, index + 1, newArr.GetTaggedValue());
150 }
151 
AddGlobalHandlerKey(JSHandle<JSTaggedValue> key,JSHandle<JSTaggedValue> handler) const152 void ProfileTypeAccessor::AddGlobalHandlerKey(JSHandle<JSTaggedValue> key, JSHandle<JSTaggedValue> handler) const
153 {
154     auto index = slotId_;
155     const uint8_t step = 2;  // key and value pair
156     JSTaggedValue indexVal = profileTypeInfo_->Get(index);
157     if (indexVal.IsUndefined()) {
158         auto factory = thread_->GetEcmaVM()->GetFactory();
159         JSHandle<TaggedArray> newArr = factory->NewTaggedArray(step);
160         newArr->Set(thread_, 0, GetWeakRef(key.GetTaggedValue()));
161         newArr->Set(thread_, 1, handler.GetTaggedValue());
162         profileTypeInfo_->Set(thread_, index, newArr.GetTaggedValue());
163         return;
164     }
165     ASSERT(indexVal.IsTaggedArray());
166     JSHandle<TaggedArray> arr(thread_, indexVal);
167     uint32_t newLen = arr->GetLength() + step;
168     if (newLen > CACHE_MAX_LEN) {
169         profileTypeInfo_->Set(thread_, index, JSTaggedValue::Hole());
170         return;
171     }
172     auto factory = thread_->GetEcmaVM()->GetFactory();
173     JSHandle<TaggedArray> newArr = factory->NewTaggedArray(newLen);
174     newArr->Set(thread_, 0, GetWeakRef(key.GetTaggedValue()));
175     newArr->Set(thread_, 1, handler.GetTaggedValue());
176 
177     for (uint32_t i = 0; i < arr->GetLength(); i += step) {
178         newArr->Set(thread_, i + step, arr->Get(i));
179         newArr->Set(thread_, i + step + 1, arr->Get(i + 1));
180     }
181     profileTypeInfo_->Set(thread_, index, newArr.GetTaggedValue());
182 }
183 
AddGlobalRecordHandler(JSHandle<JSTaggedValue> handler) const184 void ProfileTypeAccessor::AddGlobalRecordHandler(JSHandle<JSTaggedValue> handler) const
185 {
186     uint32_t index = slotId_;
187     profileTypeInfo_->Set(thread_, index, handler.GetTaggedValue());
188 }
189 
SetAsMega() const190 void ProfileTypeAccessor::SetAsMega() const
191 {
192     profileTypeInfo_->Set(thread_, slotId_, JSTaggedValue::Hole());
193     profileTypeInfo_->Set(thread_, slotId_ + 1, JSTaggedValue::Hole());
194 }
195 
ICKindToString(ICKind kind)196 std::string ICKindToString(ICKind kind)
197 {
198     switch (kind) {
199         case ICKind::NamedLoadIC:
200             return "NamedLoadIC";
201         case ICKind::NamedStoreIC:
202             return "NamedStoreIC";
203         case ICKind::LoadIC:
204             return "LoadIC";
205         case ICKind::StoreIC:
206             return "StoreIC";
207         case ICKind::NamedGlobalLoadIC:
208             return "NamedGlobalLoadIC";
209         case ICKind::NamedGlobalStoreIC:
210             return "NamedGlobalStoreIC";
211         case ICKind::NamedGlobalTryLoadIC:
212             return "NamedGlobalTryLoadIC";
213         case ICKind::NamedGlobalTryStoreIC:
214             return "NamedGlobalTryStoreIC";
215         case ICKind::GlobalLoadIC:
216             return "GlobalLoadIC";
217         case ICKind::GlobalStoreIC:
218             return "GlobalStoreIC";
219         default:
220             UNREACHABLE();
221             break;
222     }
223 }
224 
ICStateToString(ProfileTypeAccessor::ICState state)225 std::string ProfileTypeAccessor::ICStateToString(ProfileTypeAccessor::ICState state)
226 {
227     switch (state) {
228         case ICState::UNINIT:
229             return "uninit";
230         case ICState::MONO:
231             return "mono";
232         case ICState::POLY:
233             return "poly";
234         case ICState::MEGA:
235             return "mega";
236         default:
237             UNREACHABLE();
238             break;
239     }
240 }
241 
GetICState() const242 ProfileTypeAccessor::ICState ProfileTypeAccessor::GetICState() const
243 {
244     auto profileData = profileTypeInfo_->Get(slotId_);
245     if (profileData.IsUndefined()) {
246         return ICState::UNINIT;
247     }
248 
249     if (profileData.IsHole()) {
250         return ICState::MEGA;
251     }
252 
253     switch (kind_) {
254         case ICKind::NamedLoadIC:
255         case ICKind::NamedStoreIC:
256             if (profileData.IsWeak()) {
257                 return ICState::MONO;
258             }
259             ASSERT(profileData.IsTaggedArray());
260             return ICState::POLY;
261         case ICKind::LoadIC:
262         case ICKind::StoreIC: {
263             if (profileData.IsWeak()) {
264                 return ICState::MONO;
265             }
266             if (profileData.IsTaggedArray()) {
267                 TaggedArray *array = TaggedArray::Cast(profileData.GetTaggedObject());
268                 return array->GetLength() == MONO_CASE_NUM ? ICState::MONO : ICState::POLY; // 2 : test case
269             }
270             profileData = profileTypeInfo_->Get(slotId_ + 1);
271             TaggedArray *array = TaggedArray::Cast(profileData.GetTaggedObject());
272             return array->GetLength() == MONO_CASE_NUM ? ICState::MONO : ICState::POLY; // 2 : test case
273         }
274         case ICKind::NamedGlobalLoadIC:
275         case ICKind::NamedGlobalStoreIC:
276         case ICKind::NamedGlobalTryLoadIC:
277         case ICKind::NamedGlobalTryStoreIC:
278             ASSERT(profileData.IsPropertyBox());
279             return ICState::MONO;
280         case ICKind::GlobalLoadIC:
281         case ICKind::GlobalStoreIC: {
282             ASSERT(profileData.IsTaggedArray());
283             TaggedArray *array = TaggedArray::Cast(profileData.GetTaggedObject());
284             return array->GetLength() == MONO_CASE_NUM ? ICState::MONO : ICState::POLY; // 2 : test case
285         }
286         default:
287             UNREACHABLE();
288             break;
289     }
290     return ICState::UNINIT;
291 }
292 }  // namespace panda::ecmascript
293