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, ¬HeapObject);
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(¬HeapObject);
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, ¬HeapObject);
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(¬HeapObject);
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