• 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).IsHole());
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         profileTypeInfo_->Set(thread_, index, key.GetTaggedValue());
104         const int arrayLength = 2;
105         JSHandle<TaggedArray> newArr = thread_->GetEcmaVM()->GetFactory()->NewTaggedArray(arrayLength);
106         newArr->Set(thread_, 0, GetWeakRef(hclass.GetTaggedValue()));
107         newArr->Set(thread_, 1, handler.GetTaggedValue());
108         profileTypeInfo_->Set(thread_, index + 1, newArr.GetTaggedValue());
109         return;
110     }
111     // for element ic, profileData may hclass or taggedarray
112     if (key.GetTaggedValue() != profileData) {
113         profileTypeInfo_->Set(thread_, index, JSTaggedValue::Hole());
114         profileTypeInfo_->Set(thread_, index + 1, JSTaggedValue::Hole());
115         return;
116     }
117     JSTaggedValue patchValue = profileTypeInfo_->Get(index + 1);
118     ASSERT(patchValue.IsTaggedArray());
119     JSHandle<TaggedArray> arr(thread_, patchValue);
120     const uint32_t step = 2;
121     if (arr->GetLength() > step) {  // POLY
122         uint32_t newLen = arr->GetLength() + step;
123         if (newLen > CACHE_MAX_LEN) {
124             profileTypeInfo_->Set(thread_, index, JSTaggedValue::Hole());
125             profileTypeInfo_->Set(thread_, index + 1, JSTaggedValue::Hole());
126             return;
127         }
128         auto factory = thread_->GetEcmaVM()->GetFactory();
129         JSHandle<TaggedArray> newArr = factory->NewTaggedArray(newLen);
130         newArr->Set(thread_, 0, GetWeakRef(hclass.GetTaggedValue()));
131         newArr->Set(thread_, 1, handler.GetTaggedValue());
132         for (uint32_t i = 0; i < arr->GetLength(); i += step) {
133             newArr->Set(thread_, i + step, arr->Get(i));
134             newArr->Set(thread_, i + step + 1, arr->Get(i + 1));
135         }
136         profileTypeInfo_->Set(thread_, index + 1, newArr.GetTaggedValue());
137         return;
138     }
139     // MONO
140     auto factory = thread_->GetEcmaVM()->GetFactory();
141     JSHandle<TaggedArray> newArr = factory->NewTaggedArray(POLY_CASE_NUM);
142     uint32_t arrIndex = 0;
143     newArr->Set(thread_, arrIndex++, arr->Get(0));
144     newArr->Set(thread_, arrIndex++, arr->Get(1));
145     newArr->Set(thread_, arrIndex++, GetWeakRef(hclass.GetTaggedValue()));
146     newArr->Set(thread_, arrIndex++, handler.GetTaggedValue());
147 
148     profileTypeInfo_->Set(thread_, index + 1, newArr.GetTaggedValue());
149 }
150 
AddGlobalHandlerKey(JSHandle<JSTaggedValue> key,JSHandle<JSTaggedValue> handler) const151 void ProfileTypeAccessor::AddGlobalHandlerKey(JSHandle<JSTaggedValue> key, JSHandle<JSTaggedValue> handler) const
152 {
153     auto index = slotId_;
154     const uint8_t step = 2;  // key and value pair
155     JSTaggedValue indexVal = profileTypeInfo_->Get(index);
156     if (indexVal.IsUndefined()) {
157         auto factory = thread_->GetEcmaVM()->GetFactory();
158         JSHandle<TaggedArray> newArr = factory->NewTaggedArray(step);
159         newArr->Set(thread_, 0, GetWeakRef(key.GetTaggedValue()));
160         newArr->Set(thread_, 1, handler.GetTaggedValue());
161         profileTypeInfo_->Set(thread_, index, newArr.GetTaggedValue());
162         return;
163     }
164     ASSERT(indexVal.IsTaggedArray());
165     JSHandle<TaggedArray> arr(thread_, indexVal);
166     uint32_t newLen = arr->GetLength() + step;
167     if (newLen > CACHE_MAX_LEN) {
168         profileTypeInfo_->Set(thread_, index, JSTaggedValue::Hole());
169         return;
170     }
171     auto factory = thread_->GetEcmaVM()->GetFactory();
172     JSHandle<TaggedArray> newArr = factory->NewTaggedArray(newLen);
173     newArr->Set(thread_, 0, GetWeakRef(key.GetTaggedValue()));
174     newArr->Set(thread_, 1, handler.GetTaggedValue());
175 
176     for (uint32_t i = 0; i < arr->GetLength(); i += step) {
177         newArr->Set(thread_, i + step, arr->Get(i));
178         newArr->Set(thread_, i + step + 1, arr->Get(i + 1));
179     }
180     profileTypeInfo_->Set(thread_, index, newArr.GetTaggedValue());
181 }
182 
AddGlobalRecordHandler(JSHandle<JSTaggedValue> handler) const183 void ProfileTypeAccessor::AddGlobalRecordHandler(JSHandle<JSTaggedValue> handler) const
184 {
185     uint32_t index = slotId_;
186     profileTypeInfo_->Set(thread_, index, handler.GetTaggedValue());
187 }
188 
SetAsMega() const189 void ProfileTypeAccessor::SetAsMega() const
190 {
191     profileTypeInfo_->Set(thread_, slotId_, JSTaggedValue::Hole());
192     profileTypeInfo_->Set(thread_, slotId_ + 1, JSTaggedValue::Hole());
193 }
194 
ICKindToString(ICKind kind)195 std::string ICKindToString(ICKind kind)
196 {
197     switch (kind) {
198         case ICKind::NamedLoadIC:
199             return "NamedLoadIC";
200         case ICKind::NamedStoreIC:
201             return "NamedStoreIC";
202         case ICKind::LoadIC:
203             return "LoadIC";
204         case ICKind::StoreIC:
205             return "StoreIC";
206         case ICKind::NamedGlobalLoadIC:
207             return "NamedGlobalLoadIC";
208         case ICKind::NamedGlobalStoreIC:
209             return "NamedGlobalStoreIC";
210         case ICKind::NamedGlobalTryLoadIC:
211             return "NamedGlobalTryLoadIC";
212         case ICKind::NamedGlobalTryStoreIC:
213             return "NamedGlobalTryStoreIC";
214         case ICKind::GlobalLoadIC:
215             return "GlobalLoadIC";
216         case ICKind::GlobalStoreIC:
217             return "GlobalStoreIC";
218         default:
219             LOG_ECMA(FATAL) << "this branch is unreachable";
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             LOG_ECMA(FATAL) << "this branch is unreachable";
238             UNREACHABLE();
239             break;
240     }
241 }
242 
GetICState() const243 ProfileTypeAccessor::ICState ProfileTypeAccessor::GetICState() const
244 {
245     auto profileData = profileTypeInfo_->Get(slotId_);
246     if (profileData.IsUndefined()) {
247         return ICState::UNINIT;
248     }
249 
250     if (profileData.IsHole()) {
251         return ICState::MEGA;
252     }
253 
254     switch (kind_) {
255         case ICKind::NamedLoadIC:
256         case ICKind::NamedStoreIC:
257             if (profileData.IsWeak()) {
258                 return ICState::MONO;
259             }
260             ASSERT(profileData.IsTaggedArray());
261             return ICState::POLY;
262         case ICKind::LoadIC:
263         case ICKind::StoreIC: {
264             if (profileData.IsWeak()) {
265                 return ICState::MONO;
266             }
267             if (profileData.IsTaggedArray()) {
268                 TaggedArray *array = TaggedArray::Cast(profileData.GetTaggedObject());
269                 return array->GetLength() == MONO_CASE_NUM ? ICState::MONO : ICState::POLY; // 2 : test case
270             }
271             profileData = profileTypeInfo_->Get(slotId_ + 1);
272             TaggedArray *array = TaggedArray::Cast(profileData.GetTaggedObject());
273             return array->GetLength() == MONO_CASE_NUM ? ICState::MONO : ICState::POLY; // 2 : test case
274         }
275         case ICKind::NamedGlobalLoadIC:
276         case ICKind::NamedGlobalStoreIC:
277         case ICKind::NamedGlobalTryLoadIC:
278         case ICKind::NamedGlobalTryStoreIC:
279             ASSERT(profileData.IsPropertyBox());
280             return ICState::MONO;
281         case ICKind::GlobalLoadIC:
282         case ICKind::GlobalStoreIC: {
283             ASSERT(profileData.IsTaggedArray());
284             TaggedArray *array = TaggedArray::Cast(profileData.GetTaggedObject());
285             return array->GetLength() == MONO_CASE_NUM ? ICState::MONO : ICState::POLY; // 2 : test case
286         }
287         default:
288             LOG_ECMA(FATAL) << "this branch is unreachable";
289             UNREACHABLE();
290             break;
291     }
292     return ICState::UNINIT;
293 }
294 }  // namespace panda::ecmascript
295