• 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 namespace panda::ecmascript {
AddElementHandler(JSHandle<JSTaggedValue> hclass,JSHandle<JSTaggedValue> handler) const19 void ProfileTypeAccessor::AddElementHandler(JSHandle<JSTaggedValue> hclass, JSHandle<JSTaggedValue> handler) const
20 {
21     ALLOW_LOCAL_TO_SHARE_WEAK_REF_HANDLE;
22     auto profileData = profileTypeInfo_->GetIcSlot(slotId_);
23     ASSERT(!profileData.IsHole());
24     auto index = slotId_;
25     if (profileData.IsUndefined()) {
26         profileTypeInfo_->SetMultiIcSlotLocked(thread_, index, GetWeakRef(hclass.GetTaggedValue()),
27             index + 1, handler.GetTaggedValue());
28         return;
29     }
30     // clear key ic
31     if (!profileData.IsWeak() && (profileData.IsString() || profileData.IsSymbol())) {
32         profileTypeInfo_->SetMultiIcSlotLocked(thread_, index, GetWeakRef(hclass.GetTaggedValue()),
33             index + 1, handler.GetTaggedValue());
34         return;
35     }
36     AddHandlerWithoutKey(hclass, handler);
37 }
38 
AddWithoutKeyPoly(JSHandle<JSTaggedValue> hclass,JSHandle<JSTaggedValue> handler,uint32_t index,JSTaggedValue profileData) const39 void ProfileTypeAccessor::AddWithoutKeyPoly(JSHandle<JSTaggedValue> hclass, JSHandle<JSTaggedValue> handler,
40                                             uint32_t index, JSTaggedValue profileData) const
41 {
42     ASSERT(profileTypeInfo_->Get(index + 1).IsHole());
43     JSHandle<TaggedArray> arr(thread_, profileData);
44     const uint32_t step = 2;
45     uint32_t newLen = arr->GetLength() + step;
46     if (newLen > CACHE_MAX_LEN) {
47         profileTypeInfo_->SetMultiIcSlotLocked(thread_, index, JSTaggedValue::Hole(), index + 1, JSTaggedValue::Hole());
48         return;
49     }
50     auto factory = thread_->GetEcmaVM()->GetFactory();
51     JSHandle<TaggedArray> newArr = factory->NewTaggedArray(newLen);
52     uint32_t i = 0;
53     for (; i < arr->GetLength(); i += step) {
54         newArr->Set(thread_, i, arr->Get(i));
55         newArr->Set(thread_, i + 1, arr->Get(i + 1));
56     }
57     newArr->Set(thread_, i, GetWeakRef(hclass.GetTaggedValue()));
58     newArr->Set(thread_, i + 1, handler.GetTaggedValue());
59     profileTypeInfo_->SetMultiIcSlotLocked(thread_, index, newArr.GetTaggedValue(), index + 1, JSTaggedValue::Hole());
60 }
61 
AddHandlerWithoutKey(JSHandle<JSTaggedValue> hclass,JSHandle<JSTaggedValue> handler) const62 void ProfileTypeAccessor::AddHandlerWithoutKey(JSHandle<JSTaggedValue> hclass, JSHandle<JSTaggedValue> handler) const
63 {
64     ALLOW_LOCAL_TO_SHARE_WEAK_REF_HANDLE;
65     auto index = slotId_;
66     if (IsNamedGlobalIC(GetKind())) {
67         profileTypeInfo_->SetIcSlot(thread_, index, handler.GetTaggedValue());
68         return;
69     }
70     auto profileData = profileTypeInfo_->GetIcSlot(slotId_);
71     ASSERT(!profileData.IsHole());
72     if (profileData.IsUndefined()) {
73         profileTypeInfo_->SetMultiIcSlotLocked(thread_, index, GetWeakRef(hclass.GetTaggedValue()),
74             index + 1, handler.GetTaggedValue());
75         return;
76     }
77     if (!profileData.IsWeak() && profileData.IsTaggedArray()) {  // POLY
78         AddWithoutKeyPoly(hclass, handler, index, profileData);
79         return;
80     }
81     // MONO to POLY
82     auto factory = thread_->GetEcmaVM()->GetFactory();
83     JSHandle<TaggedArray> newArr = factory->NewTaggedArray(POLY_CASE_NUM);
84     uint32_t arrIndex = 0;
85     newArr->Set(thread_, arrIndex++, profileTypeInfo_->GetIcSlot(index));
86     newArr->Set(thread_, arrIndex++, profileTypeInfo_->GetIcSlot(index + 1));
87     newArr->Set(thread_, arrIndex++, GetWeakRef(hclass.GetTaggedValue()));
88     newArr->Set(thread_, arrIndex, handler.GetTaggedValue());
89 
90     profileTypeInfo_->SetMultiIcSlotLocked(thread_, index, newArr.GetTaggedValue(), index + 1, JSTaggedValue::Hole());
91 }
92 
AddHandlerWithKey(JSHandle<JSTaggedValue> key,JSHandle<JSTaggedValue> hclass,JSHandle<JSTaggedValue> handler) const93 void ProfileTypeAccessor::AddHandlerWithKey(JSHandle<JSTaggedValue> key, JSHandle<JSTaggedValue> hclass,
94                                             JSHandle<JSTaggedValue> handler) const
95 {
96     ALLOW_LOCAL_TO_SHARE_WEAK_REF_HANDLE;
97     if (IsValueGlobalIC(GetKind())) {
98         AddGlobalHandlerKey(key, handler);
99         return;
100     }
101     auto profileData = profileTypeInfo_->GetIcSlot(slotId_);
102     ASSERT(!profileData.IsHole());
103     auto index = slotId_;
104     if (profileData.IsUndefined()) {
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_->SetMultiIcSlotLocked(thread_, index,
110             key.GetTaggedValue(), index + 1, newArr.GetTaggedValue());
111         return;
112     }
113     // for element ic, profileData may hclass or tagged array
114     if (key.GetTaggedValue() != profileData) {
115         profileTypeInfo_->SetMultiIcSlotLocked(thread_, index, JSTaggedValue::Hole(), index + 1, JSTaggedValue::Hole());
116         return;
117     }
118     JSTaggedValue patchValue = profileTypeInfo_->GetIcSlot(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_->SetMultiIcSlotLocked(thread_, index,
126                 JSTaggedValue::Hole(), 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_->SetIcSlot(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_->SetIcSlot(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     ALLOW_LOCAL_TO_SHARE_WEAK_REF_HANDLE;
155     auto index = slotId_;
156     const uint8_t step = 2;  // key and value pair
157     JSTaggedValue indexVal = profileTypeInfo_->GetIcSlot(index);
158     if (indexVal.IsUndefined()) {
159         auto factory = thread_->GetEcmaVM()->GetFactory();
160         JSHandle<TaggedArray> newArr = factory->NewTaggedArray(step);
161         newArr->Set(thread_, 0, GetWeakRef(key.GetTaggedValue()));
162         newArr->Set(thread_, 1, handler.GetTaggedValue());
163         profileTypeInfo_->SetIcSlot(thread_, index, newArr.GetTaggedValue());
164         return;
165     }
166     ASSERT(indexVal.IsTaggedArray());
167     JSHandle<TaggedArray> arr(thread_, indexVal);
168     uint32_t newLen = arr->GetLength() + step;
169     if (newLen > CACHE_MAX_LEN) {
170         profileTypeInfo_->SetIcSlot(thread_, index, JSTaggedValue::Hole());
171         return;
172     }
173     auto factory = thread_->GetEcmaVM()->GetFactory();
174     JSHandle<TaggedArray> newArr = factory->NewTaggedArray(newLen);
175     newArr->Set(thread_, 0, GetWeakRef(key.GetTaggedValue()));
176     newArr->Set(thread_, 1, handler.GetTaggedValue());
177 
178     for (uint32_t i = 0; i < arr->GetLength(); i += step) {
179         newArr->Set(thread_, i + step, arr->Get(i));
180         newArr->Set(thread_, i + step + 1, arr->Get(i + 1));
181     }
182     profileTypeInfo_->SetIcSlot(thread_, index, newArr.GetTaggedValue());
183 }
184 
AddGlobalRecordHandler(JSHandle<JSTaggedValue> handler) const185 void ProfileTypeAccessor::AddGlobalRecordHandler(JSHandle<JSTaggedValue> handler) const
186 {
187     uint32_t index = slotId_;
188     profileTypeInfo_->SetIcSlot(thread_, index, handler.GetTaggedValue());
189 }
190 
SetAsMega() const191 void ProfileTypeAccessor::SetAsMega() const
192 {
193     if (IsGlobalIC(kind_)) {
194         profileTypeInfo_->SetIcSlot(thread_, slotId_, JSTaggedValue::Hole());
195     } else {
196         profileTypeInfo_->SetMultiIcSlotLocked(thread_, slotId_,
197             JSTaggedValue::Hole(), slotId_ + 1, JSTaggedValue::Hole());
198     }
199 }
200 
ICKindToString(ICKind kind)201 std::string ICKindToString(ICKind kind)
202 {
203     switch (kind) {
204         case ICKind::NamedLoadIC:
205             return "NamedLoadIC";
206         case ICKind::NamedStoreIC:
207             return "NamedStoreIC";
208         case ICKind::LoadIC:
209             return "LoadIC";
210         case ICKind::StoreIC:
211             return "StoreIC";
212         case ICKind::NamedGlobalLoadIC:
213             return "NamedGlobalLoadIC";
214         case ICKind::NamedGlobalStoreIC:
215             return "NamedGlobalStoreIC";
216         case ICKind::NamedGlobalTryLoadIC:
217             return "NamedGlobalTryLoadIC";
218         case ICKind::NamedGlobalTryStoreIC:
219             return "NamedGlobalTryStoreIC";
220         case ICKind::GlobalLoadIC:
221             return "GlobalLoadIC";
222         case ICKind::GlobalStoreIC:
223             return "GlobalStoreIC";
224         default:
225             LOG_ECMA(FATAL) << "this branch is unreachable";
226             UNREACHABLE();
227             break;
228     }
229 }
230 
ICStateToString(ProfileTypeAccessor::ICState state)231 std::string ProfileTypeAccessor::ICStateToString(ProfileTypeAccessor::ICState state)
232 {
233     switch (state) {
234         case ICState::UNINIT:
235             return "uninit";
236         case ICState::MONO:
237             return "mono";
238         case ICState::POLY:
239             return "poly";
240         case ICState::MEGA:
241             return "mega";
242         default:
243             LOG_ECMA(FATAL) << "this branch is unreachable";
244             UNREACHABLE();
245             break;
246     }
247 }
248 
GetICState() const249 ProfileTypeAccessor::ICState ProfileTypeAccessor::GetICState() const
250 {
251     auto profileData = profileTypeInfo_->GetIcSlot(slotId_);
252     if (profileData.IsUndefined()) {
253         return ICState::UNINIT;
254     }
255 
256     if (profileData.IsHole()) {
257         return ICState::MEGA;
258     }
259 
260     switch (kind_) {
261         case ICKind::NamedLoadIC:
262         case ICKind::NamedStoreIC:
263             if (profileData.IsWeak()) {
264                 return ICState::MONO;
265             }
266             ASSERT(profileData.IsTaggedArray());
267             return ICState::POLY;
268         case ICKind::LoadIC:
269         case ICKind::StoreIC: {
270             if (profileData.IsWeak()) {
271                 return ICState::MONO;
272             }
273             if (profileData.IsTaggedArray()) {
274                 TaggedArray *array = TaggedArray::Cast(profileData.GetTaggedObject());
275                 return array->GetLength() == MONO_CASE_NUM ? ICState::MONO : ICState::POLY; // 2 : test case
276             }
277             profileData = profileTypeInfo_->GetIcSlot(slotId_ + 1);
278             TaggedArray *array = TaggedArray::Cast(profileData.GetTaggedObject());
279             return array->GetLength() == MONO_CASE_NUM ? ICState::MONO : ICState::POLY; // 2 : test case
280         }
281         case ICKind::NamedGlobalLoadIC:
282         case ICKind::NamedGlobalStoreIC:
283         case ICKind::NamedGlobalTryLoadIC:
284         case ICKind::NamedGlobalTryStoreIC:
285             ASSERT(profileData.IsPropertyBox());
286             return ICState::MONO;
287         case ICKind::GlobalLoadIC:
288         case ICKind::GlobalStoreIC: {
289             ASSERT(profileData.IsTaggedArray());
290             TaggedArray *array = TaggedArray::Cast(profileData.GetTaggedObject());
291             return array->GetLength() == MONO_CASE_NUM ? ICState::MONO : ICState::POLY; // 2 : test case
292         }
293         default:
294             LOG_ECMA(FATAL) << "this branch is unreachable";
295             UNREACHABLE();
296             break;
297     }
298     return ICState::UNINIT;
299 }
300 }  // namespace panda::ecmascript
301