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