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