• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 #include "ecmascript/compiler/ic_stub_builder.h"
16 
17 #include "ecmascript/compiler/builtins/builtins_typedarray_stub_builder.h"
18 #include "ecmascript/compiler/stub_builder-inl.h"
19 
20 namespace panda::ecmascript::kungfu {
21 template<ICStubType type>
NamedICAccessor(Variable * cachedHandler,Label * tryICHandler)22 void ICStubBuilder::NamedICAccessor(Variable* cachedHandler, Label *tryICHandler)
23 {
24     auto env = GetEnvironment();
25     Label receiverIsHeapObject(env);
26     Label receiverNotHeapObject(env);
27     Label tryIC(env);
28     if constexpr (type == ICStubType::LOAD) {
29         BRANCH(TaggedIsHeapObject(receiver_), &receiverIsHeapObject, &receiverNotHeapObject);
30     } else {
31         BRANCH(TaggedIsHeapObject(receiver_), &receiverIsHeapObject, slowPath_);
32     }
33     Bind(&receiverIsHeapObject);
34     {
35         BRANCH(TaggedIsUndefined(profileTypeInfo_), tryFastPath_, &tryIC);
36         Bind(&tryIC);
37         {
38             Label isHeapObject(env);
39             Label notHeapObject(env);
40             GateRef firstValue = GetValueFromTaggedArray(
41                 profileTypeInfo_, slotId_);
42             BRANCH(TaggedIsHeapObject(firstValue), &isHeapObject, &notHeapObject);
43             Bind(&isHeapObject);
44             {
45                 GateRef secondValue = GetValueFromTaggedArray(profileTypeInfo_, Int32Add(slotId_, Int32(1)));
46                 cachedHandler->WriteVariable(secondValue);
47                 Label tryPoly(env);
48                 GateRef hclass = LoadHClass(receiver_);
49                 BRANCH(Equal(LoadObjectFromWeakRef(firstValue), hclass),
50                        tryICHandler,
51                        &tryPoly);
52                 Bind(&tryPoly);
53                 {
54                     cachedHandler->WriteVariable(CheckPolyHClass(firstValue, hclass));
55                     BRANCH(TaggedIsHole(cachedHandler->ReadVariable()), slowPath_, tryICHandler);
56                 }
57             }
58             Bind(&notHeapObject);
59             {
60                 BRANCH(TaggedIsUndefined(firstValue), slowPath_, tryFastPath_);
61             }
62         }
63     }
64     if constexpr (type == ICStubType::STORE) {
65         return;
66     }
67     Bind(&receiverNotHeapObject);
68     {
69         Label tryNumber(env);
70         Label profileNotUndefined(env);
71         BRANCH(TaggedIsNumber(receiver_), &tryNumber, slowPath_);
72         Bind(&tryNumber);
73         {
74             BRANCH(TaggedIsUndefined(profileTypeInfo_), slowPath_, &profileNotUndefined);
75             Bind(&profileNotUndefined);
76             {
77                 GateRef firstValue = GetValueFromTaggedArray(profileTypeInfo_, slotId_);
78                 GateRef secondValue = GetValueFromTaggedArray(profileTypeInfo_, Int32Add(slotId_, Int32(1)));
79                 cachedHandler->WriteVariable(secondValue);
80                 Label isHeapObject(env);
81                 BRANCH(TaggedIsHeapObject(firstValue), &isHeapObject, slowPath_)
82                 Bind(&isHeapObject);
83                 {
84                     GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
85                     GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue_, glueGlobalEnvOffset);
86                     auto numberFunction = GetGlobalEnvValue(VariableType::JS_ANY(),
87                                                             glueGlobalEnv, GlobalEnv::NUMBER_FUNCTION_INDEX);
88                     GateRef ctorProtoOrHC =
89                             Load(VariableType::JS_POINTER(), numberFunction,
90                                  IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
91                     BRANCH(Equal(LoadObjectFromWeakRef(firstValue), ctorProtoOrHC), tryICHandler, slowPath_);
92                 }
93             }
94         }
95     }
96 }
97 
ValuedICAccessor(Variable * cachedHandler,Label * tryICHandler,Label * tryElementIC)98 void ICStubBuilder::ValuedICAccessor(Variable* cachedHandler, Label *tryICHandler, Label* tryElementIC)
99 {
100     auto env = GetEnvironment();
101     Label receiverIsHeapObject(env);
102 
103     BRANCH(TaggedIsHeapObject(receiver_), &receiverIsHeapObject, slowPath_);
104     Bind(&receiverIsHeapObject);
105     {
106         Label tryIC(env);
107         BRANCH(TaggedIsUndefined(profileTypeInfo_), tryFastPath_, &tryIC);
108         Bind(&tryIC);
109         {
110             Label isHeapObject(env);
111             Label notHeapObject(env);
112             GateRef firstValue = GetValueFromTaggedArray(
113                 profileTypeInfo_, slotId_);
114             BRANCH(TaggedIsHeapObject(firstValue), &isHeapObject, &notHeapObject);
115             Bind(&isHeapObject);
116             {
117                 Label tryPoly(env);
118                 Label tryWithElementPoly(env);
119                 GateRef hclass = LoadHClass(receiver_);
120                 BRANCH(Equal(LoadObjectFromWeakRef(firstValue), hclass),
121                        tryElementIC,
122                        &tryPoly);
123                 Bind(&tryPoly);
124                 {
125                     Label firstIsKey(env);
126                     BRANCH(Int64Equal(firstValue, propKey_), &firstIsKey, &tryWithElementPoly);
127                     Bind(&firstIsKey);
128                     {
129                         GateRef handler = CheckPolyHClass(cachedHandler->ReadVariable(), hclass);
130                         cachedHandler->WriteVariable(handler);
131                         BRANCH(TaggedIsHole(cachedHandler->ReadVariable()), slowPath_, tryICHandler);
132                     }
133                     Bind(&tryWithElementPoly);
134                     {
135                         Label checkSecond(env);
136                         Label checkPoly(env);
137                         BRANCH(TaggedIsWeak(firstValue), slowPath_, &checkSecond);
138                         Bind(&checkSecond);
139                         {
140                             BRANCH(TaggedIsHole(cachedHandler->ReadVariable()), &checkPoly, slowPath_);
141                         }
142                         Bind(&checkPoly);
143                         {
144                             cachedHandler->WriteVariable(CheckPolyHClass(firstValue, hclass));
145                             BRANCH(TaggedIsHole(cachedHandler->ReadVariable()), slowPath_, tryElementIC);
146                         }
147                     }
148                 }
149             }
150             Bind(&notHeapObject);
151             {
152                 BRANCH(TaggedIsUndefined(firstValue), slowPath_, tryFastPath_);
153             }
154         }
155     }
156 }
157 
LoadICByName(Variable * result,Label * tryFastPath,Label * slowPath,Label * success,ProfileOperation callback)158 void ICStubBuilder::LoadICByName(
159     Variable *result, Label *tryFastPath, Label *slowPath, Label *success, ProfileOperation callback)
160 {
161     auto env = GetEnvironment();
162     Label loadWithHandler(env);
163 
164     SetLabels(tryFastPath, slowPath, success);
165     DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), Undefined());
166     NamedICAccessor<ICStubType::LOAD>(&cachedHandler, &loadWithHandler);
167     Bind(&loadWithHandler);
168     {
169         GateRef ret = LoadICWithHandler(glue_, receiver_, receiver_, *cachedHandler, callback);
170         result->WriteVariable(ret);
171         BRANCH(TaggedIsHole(ret), slowPath_, success_);
172     }
173 }
174 
StoreICByName(Variable * result,Label * tryFastPath,Label * slowPath,Label * success)175 void ICStubBuilder::StoreICByName(Variable* result, Label* tryFastPath, Label *slowPath, Label *success)
176 {
177     auto env = GetEnvironment();
178     Label storeWithHandler(env);
179 
180     SetLabels(tryFastPath, slowPath, success);
181     GateRef secondValue = GetValueFromTaggedArray(
182         profileTypeInfo_, Int32Add(slotId_, Int32(1)));
183     DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), secondValue);
184     NamedICAccessor<ICStubType::STORE>(&cachedHandler, &storeWithHandler);
185     Bind(&storeWithHandler);
186     {
187         GateRef ret = StoreICWithHandler(glue_, receiver_, receiver_, value_, *cachedHandler, callback_);
188         result->WriteVariable(ret);
189         BRANCH(TaggedIsHole(ret), slowPath_, success_);
190     }
191 }
192 
LoadICByValue(Variable * result,Label * tryFastPath,Label * slowPath,Label * success,ProfileOperation callback)193 void ICStubBuilder::LoadICByValue(
194     Variable *result, Label *tryFastPath, Label *slowPath, Label *success, ProfileOperation callback)
195 {
196     auto env = GetEnvironment();
197     Label loadWithHandler(env);
198     Label loadElement(env);
199     Label handlerInfoIsElement(env);
200     Label handlerInfoNotElement(env);
201     Label handlerInfoIsStringElement(env);
202     Label handlerInfoNotStringElement(env);
203     Label handlerInfoIsTypedArrayElement(env);
204     Label exit(env);
205 
206     SetLabels(tryFastPath, slowPath, success);
207     GateRef secondValue = GetValueFromTaggedArray(
208         profileTypeInfo_, Int32Add(slotId_, Int32(1)));
209     DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), secondValue);
210     DEFVARIABLE(ret, VariableType::JS_ANY(), secondValue);
211 
212     ValuedICAccessor(&cachedHandler, &loadWithHandler, &loadElement);
213     Bind(&loadElement);
214     {
215         GateRef handlerInfo = GetInt64OfTInt(*cachedHandler);
216         BRANCH(IsElement(handlerInfo), &handlerInfoIsElement, &handlerInfoNotElement);
217         Bind(&handlerInfoIsElement);
218         {
219             ret = LoadElement(glue_, receiver_, propKey_);
220             Jump(&exit);
221         }
222         Bind(&handlerInfoNotElement);
223         {
224             BRANCH(IsStringElement(handlerInfo), &handlerInfoIsStringElement, &handlerInfoNotStringElement);
225             Bind(&handlerInfoIsStringElement);
226             {
227                 ret = LoadStringElement(glue_, receiver_, propKey_);
228                 Jump(&exit);
229             }
230             Bind(&handlerInfoNotStringElement);
231             {
232                 BRANCH(IsTypedArrayElement(handlerInfo), &handlerInfoIsTypedArrayElement, &exit);
233                 Bind(&handlerInfoIsTypedArrayElement);
234                 {
235                     GateRef hclass = LoadHClass(receiver_);
236                     GateRef jsType = GetObjectType(hclass);
237                     BuiltinsTypedArrayStubBuilder typedArrayBuilder(reinterpret_cast<StubBuilder*>(this));
238                     ret = typedArrayBuilder.LoadTypedArrayElement(glue_, receiver_, propKey_, jsType);
239                     Jump(&exit);
240                 }
241             }
242         }
243     }
244     Bind(&loadWithHandler);
245     {
246         ret = LoadICWithHandler(glue_, receiver_, receiver_, *cachedHandler, callback);
247         Jump(&exit);
248     }
249     Bind(&exit);
250     result->WriteVariable(*ret);
251     BRANCH(TaggedIsHole(*ret), slowPath_, success_);
252 }
253 
StoreICByValue(Variable * result,Label * tryFastPath,Label * slowPath,Label * success)254 void ICStubBuilder::StoreICByValue(Variable* result, Label* tryFastPath, Label *slowPath, Label *success)
255 {
256     auto env = GetEnvironment();
257     Label storeWithHandler(env);
258     Label storeElement(env);
259     SetLabels(tryFastPath, slowPath, success);
260     GateRef secondValue = GetValueFromTaggedArray(
261         profileTypeInfo_, Int32Add(slotId_, Int32(1)));
262     DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), secondValue);
263     ValuedICAccessor(&cachedHandler, &storeWithHandler, &storeElement);
264     Bind(&storeElement);
265     {
266         GateRef ret = ICStoreElement(glue_, receiver_, propKey_, value_, *cachedHandler,
267                                      true, profileTypeInfo_, Int32Add(slotId_, Int32(1)));
268         result->WriteVariable(ret);
269         BRANCH(TaggedIsHole(ret), slowPath_, success_);
270     }
271     Bind(&storeWithHandler);
272     {
273         GateRef ret = StoreICWithHandler(glue_, receiver_, receiver_, value_, *cachedHandler, callback_);
274         result->WriteVariable(ret);
275         BRANCH(TaggedIsHole(ret), slowPath_, success_);
276     }
277 }
278 
TryLoadGlobalICByName(Variable * result,Label * tryFastPath,Label * slowPath,Label * success)279 void ICStubBuilder::TryLoadGlobalICByName(Variable* result, Label* tryFastPath, Label *slowPath, Label *success)
280 {
281     auto env = GetEnvironment();
282     Label tryIC(env);
283 
284     SetLabels(tryFastPath, slowPath, success);
285     BRANCH(TaggedIsUndefined(profileTypeInfo_), tryFastPath_, &tryIC);
286     Bind(&tryIC);
287     {
288         GateRef handler = GetValueFromTaggedArray(profileTypeInfo_, slotId_);
289         Label isHeapObject(env);
290         BRANCH(TaggedIsHeapObject(handler), &isHeapObject, slowPath_);
291         Bind(&isHeapObject);
292         {
293             GateRef ret = LoadGlobal(handler);
294             result->WriteVariable(ret);
295             BRANCH(TaggedIsHole(ret), slowPath_, success_);
296         }
297     }
298 }
299 
TryStoreGlobalICByName(Variable * result,Label * tryFastPath,Label * slowPath,Label * success)300 void ICStubBuilder::TryStoreGlobalICByName(Variable* result, Label* tryFastPath, Label *slowPath, Label *success)
301 {
302     auto env = GetEnvironment();
303     Label tryIC(env);
304 
305     SetLabels(tryFastPath, slowPath, success);
306     BRANCH(TaggedIsUndefined(profileTypeInfo_), tryFastPath_, &tryIC);
307     Bind(&tryIC);
308     {
309         GateRef handler = GetValueFromTaggedArray(profileTypeInfo_, slotId_);
310         Label isHeapObject(env);
311         BRANCH(TaggedIsHeapObject(handler), &isHeapObject, slowPath_);
312         Bind(&isHeapObject);
313         {
314             GateRef ret = StoreGlobal(glue_, value_, handler);
315             result->WriteVariable(ret);
316             BRANCH(TaggedIsHole(ret), slowPath_, success_);
317         }
318     }
319 }
320 }  // namespace panda::ecmascript::kungfu
321