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 "fast_stub.h"
17
18 #include "ecmascript/base/number_helper.h"
19 #include "ecmascript/compiler/llvm_ir_builder.h"
20 #include "ecmascript/compiler/machine_type.h"
21 #include "ecmascript/js_array.h"
22 #include "ecmascript/message_string.h"
23 #include "ecmascript/tagged_hash_table-inl.h"
24
25 namespace panda::ecmascript::kungfu {
26 using namespace panda::ecmascript;
27
28 #ifndef NDEBUG
GenerateCircuit(const CompilationConfig * cfg)29 void PhiGateTestStub::GenerateCircuit(const CompilationConfig *cfg)
30 {
31 Stub::GenerateCircuit(cfg);
32 auto env = GetEnvironment();
33 DEFVARIABLE(z, StubMachineType::INT32, GetInt32Constant(0));
34 DEFVARIABLE(x, StubMachineType::INT32, Int32Argument(0));
35 Label ifTrue(env);
36 Label ifFalse(env);
37 Label next(env);
38
39 Branch(Int32Equal(*x, GetInt32Constant(10)), &ifTrue, &ifFalse); // 10 : size of entry
40 Bind(&ifTrue);
41 z = Int32Add(*x, GetInt32Constant(10)); // 10 : size of entry
42 Jump(&next);
43 Bind(&ifFalse);
44 z = Int32Add(*x, GetInt32Constant(100)); // 100 : size of entry
45 Jump(&next);
46 Bind(&next);
47 Return(*z);
48 }
49
GenerateCircuit(const CompilationConfig * cfg)50 void LoopTestStub::GenerateCircuit(const CompilationConfig *cfg)
51 {
52 Stub::GenerateCircuit(cfg);
53 auto env = GetEnvironment();
54 DEFVARIABLE(z, StubMachineType::INT32, GetInt32Constant(0));
55 DEFVARIABLE(y, StubMachineType::INT32, Int32Argument(0));
56 Label loopHead(env);
57 Label loopEnd(env);
58 Label afterLoop(env);
59 Branch(Int32LessThan(*y, GetInt32Constant(10)), &loopHead, &afterLoop); // 10 : size of entry
60 LoopBegin(&loopHead);
61 Label ifTrue(env);
62 Label ifFalse(env);
63 Label next(env);
64 Branch(Int32Equal(Int32Argument(0), GetInt32Constant(9)), &ifTrue, &ifFalse); // 9 : size of entry
65 Bind(&ifTrue);
66 z = Int32Add(*y, GetInt32Constant(10)); // 10 : size of entry
67 y = Int32Add(*z, GetInt32Constant(1));
68 Jump(&next);
69 Bind(&ifFalse);
70 z = Int32Add(*y, GetInt32Constant(100)); // 100 : size of entry
71 Jump(&next);
72 Bind(&next);
73 y = Int32Add(*y, GetInt32Constant(1));
74 Branch(Int32LessThan(*y, GetInt32Constant(10)), &loopEnd, &afterLoop); // 10 : size of entry
75 Bind(&loopEnd);
76 LoopEnd(&loopHead);
77 Bind(&afterLoop);
78 Return(*z);
79 }
80
GenerateCircuit(const CompilationConfig * cfg)81 void LoopTest1Stub::GenerateCircuit(const CompilationConfig *cfg)
82 {
83 Stub::GenerateCircuit(cfg);
84 auto env = GetEnvironment();
85 DEFVARIABLE(y, StubMachineType::INT32, Int32Argument(0));
86 DEFVARIABLE(x, StubMachineType::INT32, Int32Argument(0));
87 DEFVARIABLE(z, StubMachineType::INT32, Int32Argument(0));
88 Label loopHead(env);
89 Label loopEnd(env);
90 Label afterLoop(env);
91 Branch(Int32LessThan(*y, GetInt32Constant(10)), &loopHead, &afterLoop); // 10 : size of entry
92 LoopBegin(&loopHead);
93 x = Int32Add(*z, GetInt32Constant(3)); // 3 : size of entry
94 Label ifTrue(env);
95 Label next(env);
96 Branch(Int32Equal(*x, GetInt32Constant(9)), &ifTrue, &next); // 9 : size of entry
97 Bind(&ifTrue);
98 y = Int32Add(*z, *x);
99 Jump(&next);
100 Bind(&next);
101 y = Int32Add(*y, GetInt32Constant(1));
102 Branch(Int32LessThan(*y, GetInt32Constant(10)), &loopEnd, &afterLoop); // 10 : size of entry
103 Bind(&loopEnd);
104 LoopEnd(&loopHead);
105 Bind(&afterLoop);
106 z = *y;
107 Return(*z);
108 }
109
GenerateCircuit(const CompilationConfig * cfg)110 void FastMulGCTestStub::GenerateCircuit(const CompilationConfig *cfg)
111 {
112 Stub::GenerateCircuit(cfg);
113 auto env = GetEnvironment();
114 GateRef glue = PtrArgument(0);
115 GateRef x = Int64Argument(1);
116 GateRef y = Int64Argument(2); // 2: 3rd argument
117
118 DEFVARIABLE(intX, StubMachineType::INT64, GetInt64Constant(0));
119 DEFVARIABLE(intY, StubMachineType::INT64, GetInt64Constant(0));
120 DEFVARIABLE(valuePtr, StubMachineType::INT64, GetInt64Constant(0));
121 DEFVARIABLE(doubleX, StubMachineType::FLOAT64, GetDoubleConstant(0));
122 DEFVARIABLE(doubleY, StubMachineType::FLOAT64, GetDoubleConstant(0));
123 Label xIsNumber(env);
124 Label xNotNumberOryNotNumber(env);
125 Label xIsNumberAndyIsNumber(env);
126 Label xIsDoubleAndyIsDouble(env);
127 Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber);
128 Bind(&xIsNumber);
129 {
130 Label yIsNumber(env);
131 // if right.IsNumber()
132 Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber);
133 Bind(&yIsNumber);
134 {
135 Label xIsInt(env);
136 Label xNotInt(env);
137 Branch(TaggedIsInt(x), &xIsInt, &xNotInt);
138 Bind(&xIsInt);
139 {
140 intX = TaggedCastToInt64(x);
141 doubleX = CastInt64ToFloat64(*intX);
142 Jump(&xIsNumberAndyIsNumber);
143 }
144 Bind(&xNotInt);
145 {
146 doubleX = TaggedCastToDouble(x);
147 Jump(&xIsNumberAndyIsNumber);
148 }
149 }
150 }
151 Bind(&xNotNumberOryNotNumber);
152 Return(GetHoleConstant(StubMachineType::TAGGED));
153 Label yIsInt(env);
154 Label yNotInt(env);
155 Bind(&xIsNumberAndyIsNumber);
156 {
157 Branch(TaggedIsInt(y), &yIsInt, &yNotInt);
158 Bind(&yIsInt);
159 {
160 intY = TaggedCastToInt64(y);
161 doubleY = CastInt64ToFloat64(*intY);
162 Jump(&xIsDoubleAndyIsDouble);
163 }
164 Bind(&yNotInt);
165 {
166 doubleY = TaggedCastToDouble(y);
167 Jump(&xIsDoubleAndyIsDouble);
168 }
169 }
170 Bind(&xIsDoubleAndyIsDouble);
171 doubleX = DoubleMul(*doubleX, *doubleY);
172 GateRef ptr1 = CallRuntimeTrampoline(glue, GetInt64Constant(FAST_STUB_ID(GetTaggedArrayPtrTest)), {});
173 GateRef ptr2 = CallRuntimeTrampoline(glue, GetInt64Constant(FAST_STUB_ID(GetTaggedArrayPtrTest)), {});
174 auto value1 = GetValueFromTaggedArray(StubMachineType::UINT64, ptr1, GetInt64Constant(0));
175 GateRef tmp = CastInt64ToFloat64(value1);
176 doubleX = DoubleMul(*doubleX, tmp);
177 auto value2 = GetValueFromTaggedArray(StubMachineType::UINT64, ptr2, GetInt64Constant(1));
178 tmp = CastInt64ToFloat64(value2);
179 doubleX = DoubleMul(*doubleX, tmp);
180 Return(DoubleBuildTaggedWithNoGC(*doubleX));
181 }
182 #endif
183
GenerateCircuit(const CompilationConfig * cfg)184 void FastAddStub::GenerateCircuit(const CompilationConfig *cfg)
185 {
186 Stub::GenerateCircuit(cfg);
187 auto env = GetEnvironment();
188 GateRef x = TaggedArgument(0);
189 GateRef y = TaggedArgument(1);
190 DEFVARIABLE(intX, StubMachineType::INT32, 0);
191 DEFVARIABLE(intY, StubMachineType::INT32, 0);
192 DEFVARIABLE(doubleX, StubMachineType::FLOAT64, 0);
193 DEFVARIABLE(doubleY, StubMachineType::FLOAT64, 0);
194 Label xIsNumber(env);
195 Label xNotNumberOryNotNumber(env);
196 Label xIsNumberAndyIsNumber(env);
197 Label xIsDoubleAndyIsDouble(env);
198 Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber);
199 Bind(&xIsNumber);
200 {
201 Label yIsNumber(env);
202 // if right.IsNumber()
203 Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber);
204 Bind(&yIsNumber);
205 {
206 Label xIsInt(env);
207 Label xNotInt(env);
208 Branch(TaggedIsInt(x), &xIsInt, &xNotInt);
209 Bind(&xIsInt);
210 {
211 intX = TaggedCastToInt32(x);
212 doubleX = ChangeInt32ToFloat64(*intX);
213 Jump(&xIsNumberAndyIsNumber);
214 }
215 Bind(&xNotInt);
216 {
217 doubleX = TaggedCastToDouble(x);
218 Jump(&xIsNumberAndyIsNumber);
219 }
220 }
221 }
222 Bind(&xNotNumberOryNotNumber);
223 Return(GetHoleConstant(StubMachineType::TAGGED));
224 Label yIsInt(env);
225 Label yNotInt(env);
226 Bind(&xIsNumberAndyIsNumber);
227 {
228 Branch(TaggedIsInt(y), &yIsInt, &yNotInt);
229 Bind(&yIsInt);
230 {
231 intY = TaggedCastToInt32(y);
232 doubleY = ChangeInt32ToFloat64(*intY);
233 Jump(&xIsDoubleAndyIsDouble);
234 }
235 Bind(&yNotInt);
236 {
237 doubleY = TaggedCastToDouble(y);
238 Jump(&xIsDoubleAndyIsDouble);
239 }
240 }
241 Bind(&xIsDoubleAndyIsDouble);
242 doubleX = DoubleAdd(*doubleX, *doubleY);
243 Return(DoubleBuildTaggedWithNoGC(*doubleX));
244 }
245
GenerateCircuit(const CompilationConfig * cfg)246 void FastSubStub::GenerateCircuit(const CompilationConfig *cfg)
247 {
248 Stub::GenerateCircuit(cfg);
249 auto env = GetEnvironment();
250 GateRef x = TaggedArgument(0);
251 GateRef y = TaggedArgument(1);
252 DEFVARIABLE(intX, StubMachineType::INT32, GetInt32Constant(0));
253 DEFVARIABLE(intY, StubMachineType::INT32, GetInt32Constant(0));
254 DEFVARIABLE(doubleX, StubMachineType::FLOAT64, GetDoubleConstant(0));
255 DEFVARIABLE(doubleY, StubMachineType::FLOAT64, GetDoubleConstant(0));
256 Label xIsNumber(env);
257 Label xNotNumberOryNotNumber(env);
258 Label xNotIntOryNotInt(env);
259 Label xIsIntAndyIsInt(env);
260 // if x is number
261 Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber);
262 Bind(&xIsNumber);
263 {
264 Label yIsNumber(env);
265 // if y is number
266 Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber);
267 {
268 Bind(&yIsNumber);
269 {
270 Label xIsInt(env);
271 Label xNotInt(env);
272 Branch(TaggedIsInt(x), &xIsInt, &xNotInt);
273 Bind(&xIsInt);
274 {
275 intX = TaggedCastToInt32(x);
276 Label yIsInt(env);
277 Label yNotInt(env);
278 Branch(TaggedIsInt(y), &yIsInt, &yNotInt);
279 Bind(&yIsInt);
280 {
281 intY = TaggedCastToInt32(y);
282 intX = Int32Sub(*intX, *intY);
283 Jump(&xIsIntAndyIsInt);
284 }
285 Bind(&yNotInt);
286 {
287 doubleY = TaggedCastToDouble(y);
288 doubleX = ChangeInt32ToFloat64(*intX);
289 Jump(&xNotIntOryNotInt);
290 }
291 }
292 Bind(&xNotInt);
293 {
294 Label yIsInt(env);
295 Label yNotInt(env);
296 doubleX = TaggedCastToDouble(x);
297 Branch(TaggedIsInt(y), &yIsInt, &yNotInt);
298 Bind(&yIsInt);
299 {
300 intY = TaggedCastToInt32(y);
301 doubleY = ChangeInt32ToFloat64(*intY);
302 Jump(&xNotIntOryNotInt);
303 }
304 Bind(&yNotInt);
305 {
306 doubleY = TaggedCastToDouble(y);
307 Jump(&xNotIntOryNotInt);
308 }
309 }
310 }
311 }
312 }
313 Bind(&xNotNumberOryNotNumber);
314 Return(GetHoleConstant(StubMachineType::TAGGED));
315 Bind(&xNotIntOryNotInt);
316 doubleX = DoubleSub(*doubleX, *doubleY);
317 Return(DoubleBuildTaggedWithNoGC(*doubleX));
318 Bind(&xIsIntAndyIsInt);
319 Return(IntBuildTaggedWithNoGC(*intX));
320 }
321
GenerateCircuit(const CompilationConfig * cfg)322 void FastMulStub::GenerateCircuit(const CompilationConfig *cfg)
323 {
324 Stub::GenerateCircuit(cfg);
325 auto env = GetEnvironment();
326 GateRef x = TaggedArgument(0);
327 GateRef y = TaggedArgument(1);
328 DEFVARIABLE(intX, StubMachineType::INT32, GetInt32Constant(0));
329 DEFVARIABLE(intY, StubMachineType::INT32, GetInt32Constant(0));
330 DEFVARIABLE(doubleX, StubMachineType::FLOAT64, GetDoubleConstant(0));
331 DEFVARIABLE(doubleY, StubMachineType::FLOAT64, GetDoubleConstant(0));
332 Label xIsNumber(env);
333 Label xNotNumberOryNotNumber(env);
334 Label xIsNumberAndyIsNumber(env);
335 Label xIsDoubleAndyIsDouble(env);
336 Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber);
337 Bind(&xIsNumber);
338 {
339 Label yIsNumber(env);
340 // if right.IsNumber()
341 Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber);
342 Bind(&yIsNumber);
343 {
344 Label xIsInt(env);
345 Label xNotInt(env);
346 Branch(TaggedIsInt(x), &xIsInt, &xNotInt);
347 Bind(&xIsInt);
348 {
349 intX = TaggedCastToInt32(x);
350 doubleX = ChangeInt32ToFloat64(*intX);
351 Jump(&xIsNumberAndyIsNumber);
352 }
353 Bind(&xNotInt);
354 {
355 doubleX = TaggedCastToDouble(x);
356 Jump(&xIsNumberAndyIsNumber);
357 }
358 }
359 }
360 Bind(&xNotNumberOryNotNumber);
361 Return(GetHoleConstant(StubMachineType::TAGGED));
362 Label yIsInt(env);
363 Label yNotInt(env);
364 Bind(&xIsNumberAndyIsNumber);
365 {
366 Branch(TaggedIsInt(y), &yIsInt, &yNotInt);
367 Bind(&yIsInt);
368 {
369 intY = TaggedCastToInt32(y);
370 doubleY = ChangeInt32ToFloat64(*intY);
371 Jump(&xIsDoubleAndyIsDouble);
372 }
373 Bind(&yNotInt);
374 {
375 doubleY = TaggedCastToDouble(y);
376 Jump(&xIsDoubleAndyIsDouble);
377 }
378 }
379 Bind(&xIsDoubleAndyIsDouble);
380 doubleX = DoubleMul(*doubleX, *doubleY);
381 Return(DoubleBuildTaggedWithNoGC(*doubleX));
382 }
383
GenerateCircuit(const CompilationConfig * cfg)384 void FastDivStub::GenerateCircuit(const CompilationConfig *cfg)
385 {
386 Stub::GenerateCircuit(cfg);
387 auto env = GetEnvironment();
388 GateRef x = TaggedArgument(0);
389 GateRef y = TaggedArgument(1);
390 DEFVARIABLE(intX, StubMachineType::INT32, GetInt32Constant(0));
391 DEFVARIABLE(intY, StubMachineType::INT32, GetInt32Constant(0));
392 DEFVARIABLE(doubleX, StubMachineType::FLOAT64, GetDoubleConstant(0));
393 DEFVARIABLE(doubleY, StubMachineType::FLOAT64, GetDoubleConstant(0));
394 Label xIsNumber(env);
395 Label xNotNumberOryNotNumber(env);
396 Label xIsNumberAndyIsNumber(env);
397 Label xIsDoubleAndyIsDouble(env);
398 Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber);
399 Bind(&xIsNumber);
400 {
401 Label yIsNumber(env);
402 // if right.IsNumber()
403 Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber);
404 Bind(&yIsNumber);
405 {
406 Label xIsInt(env);
407 Label xNotInt(env);
408 Branch(TaggedIsInt(x), &xIsInt, &xNotInt);
409 Bind(&xIsInt);
410 {
411 intX = TaggedCastToInt32(x);
412 doubleX = ChangeInt32ToFloat64(*intX);
413 Jump(&xIsNumberAndyIsNumber);
414 }
415 Bind(&xNotInt);
416 {
417 doubleX = TaggedCastToDouble(x);
418 Jump(&xIsNumberAndyIsNumber);
419 }
420 }
421 }
422 Bind(&xNotNumberOryNotNumber);
423 Return(GetHoleConstant(StubMachineType::TAGGED));
424 Label yIsInt(env);
425 Label yNotInt(env);
426 Bind(&xIsNumberAndyIsNumber);
427 Branch(TaggedIsInt(y), &yIsInt, &yNotInt);
428 Bind(&yIsInt);
429 {
430 intY = TaggedCastToInt32(y);
431 doubleY = ChangeInt32ToFloat64(*intY);
432 Jump(&xIsDoubleAndyIsDouble);
433 }
434 Bind(&yNotInt);
435 {
436 doubleY = TaggedCastToDouble(y);
437 Jump(&xIsDoubleAndyIsDouble);
438 }
439 Bind(&xIsDoubleAndyIsDouble);
440 {
441 Label divisorIsZero(env);
442 Label divisorNotZero(env);
443 Branch(DoubleEqual(*doubleY, GetDoubleConstant(0.0)), &divisorIsZero, &divisorNotZero);
444 Bind(&divisorIsZero);
445 {
446 Label xIsZeroOrNan(env);
447 Label xNeiZeroOrNan(env);
448 Label xIsZero(env);
449 Label xNotZero(env);
450 // dLeft == 0.0 || std::isnan(dLeft)
451 Branch(DoubleEqual(*doubleX, GetDoubleConstant(0.0)), &xIsZero, &xNotZero);
452 Bind(&xIsZero);
453 Jump(&xIsZeroOrNan);
454 Bind(&xNotZero);
455 {
456 Label xIsNan(env);
457 Label xNotNan(env);
458 Branch(DoubleIsNAN(*doubleX), &xIsNan, &xNotNan);
459 Bind(&xIsNan);
460 Jump(&xIsZeroOrNan);
461 Bind(&xNotNan);
462 Jump(&xNeiZeroOrNan);
463 }
464 Bind(&xIsZeroOrNan);
465 Return(DoubleBuildTaggedWithNoGC(GetDoubleConstant(base::NAN_VALUE)));
466 Bind(&xNeiZeroOrNan);
467 {
468 GateRef intXTmp = CastDoubleToInt64(*doubleX);
469 GateRef intYtmp = CastDoubleToInt64(*doubleY);
470 intXTmp = Int64And(Int64Xor(intXTmp, intYtmp), GetInt64Constant(base::DOUBLE_SIGN_MASK));
471 intXTmp = Int64Xor(intXTmp, CastDoubleToInt64(GetDoubleConstant(base::POSITIVE_INFINITY)));
472 doubleX = CastInt64ToFloat64(intXTmp);
473 Return(DoubleBuildTaggedWithNoGC(*doubleX));
474 }
475 }
476 Bind(&divisorNotZero);
477 {
478 doubleX = DoubleDiv(*doubleX, *doubleY);
479 Return(DoubleBuildTaggedWithNoGC(*doubleX));
480 }
481 }
482 }
483
GenerateCircuit(const CompilationConfig * cfg)484 void FastModStub::GenerateCircuit(const CompilationConfig *cfg)
485 {
486 Stub::GenerateCircuit(cfg);
487 auto env = GetEnvironment();
488 GateRef glue = PtrArgument(0);
489 GateRef x = TaggedArgument(1);
490 GateRef y = TaggedArgument(2); // 2: 3rd argument
491 DEFVARIABLE(intX, StubMachineType::INT32, GetInt32Constant(0));
492 DEFVARIABLE(intY, StubMachineType::INT32, GetInt32Constant(0));
493 DEFVARIABLE(doubleX, StubMachineType::FLOAT64, GetDoubleConstant(0));
494 DEFVARIABLE(doubleY, StubMachineType::FLOAT64, GetDoubleConstant(0));
495 Label xIsInt(env);
496 Label xNotIntOryNotInt(env);
497 Branch(TaggedIsInt(x), &xIsInt, &xNotIntOryNotInt);
498 Bind(&xIsInt);
499 {
500 Label yIsInt(env);
501 Label xIsIntAndyIsInt(env);
502 // if right.IsInt()
503 Branch(TaggedIsInt(y), &yIsInt, &xNotIntOryNotInt);
504 Bind(&yIsInt);
505 {
506 intX = TaggedCastToInt32(x);
507 intY = TaggedCastToInt32(y);
508 Jump(&xIsIntAndyIsInt);
509 }
510 Bind(&xIsIntAndyIsInt);
511 {
512 Label xGtZero(env);
513 Label xGtZeroAndyGtZero(env);
514 Branch(Int32GreaterThan(*intX, GetInt32Constant(0)), &xGtZero, &xNotIntOryNotInt);
515 Bind(&xGtZero);
516 {
517 Branch(Int32GreaterThan(*intY, GetInt32Constant(0)), &xGtZeroAndyGtZero, &xNotIntOryNotInt);
518 Bind(&xGtZeroAndyGtZero);
519 {
520 intX = Int32Mod(*intX, *intY);
521 Return(IntBuildTaggedWithNoGC(*intX));
522 }
523 }
524 }
525 }
526 Bind(&xNotIntOryNotInt);
527 {
528 Label xIsNumber(env);
529 Label xNotNumberOryNotNumber(env);
530 Label xIsNumberAndyIsNumber(env);
531 Label xIsDoubleAndyIsDouble(env);
532 Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber);
533 Bind(&xIsNumber);
534 {
535 Label yIsNumber(env);
536 // if right.IsNumber()
537 Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber);
538 Bind(&yIsNumber);
539 {
540 Label xIfInt(env);
541 Label xIfNotInt(env);
542 Branch(TaggedIsInt(x), &xIfInt, &xIfNotInt);
543 Bind(&xIfInt);
544 {
545 intX = TaggedCastToInt32(x);
546 doubleX = ChangeInt32ToFloat64(*intX);
547 Jump(&xIsNumberAndyIsNumber);
548 }
549 Bind(&xIfNotInt);
550 {
551 doubleX = TaggedCastToDouble(x);
552 Jump(&xIsNumberAndyIsNumber);
553 }
554 }
555 }
556 Bind(&xNotNumberOryNotNumber);
557 Return(GetHoleConstant(StubMachineType::TAGGED));
558 Label yIfInt(env);
559 Label yIfNotInt(env);
560 Bind(&xIsNumberAndyIsNumber);
561 Branch(TaggedIsInt(y), &yIfInt, &yIfNotInt);
562 Bind(&yIfInt);
563 {
564 intY = TaggedCastToInt32(y);
565 doubleY = ChangeInt32ToFloat64(*intY);
566 Jump(&xIsDoubleAndyIsDouble);
567 }
568 Bind(&yIfNotInt);
569 {
570 doubleY = TaggedCastToDouble(y);
571 Jump(&xIsDoubleAndyIsDouble);
572 }
573 Bind(&xIsDoubleAndyIsDouble);
574 {
575 Label yIsZero(env);
576 Label yNotZero(env);
577 Label yIsZeroOrNanOrxIsNanOrInf(env);
578 Label yNeiZeroOrNanAndxNeiNanOrInf(env);
579 // dRight == 0.0 or std::isnan(dRight) or std::isnan(dLeft) or std::isinf(dLeft)
580 Branch(DoubleEqual(*doubleY, GetDoubleConstant(0.0)), &yIsZero, &yNotZero);
581 Bind(&yIsZero);
582 Jump(&yIsZeroOrNanOrxIsNanOrInf);
583 Bind(&yNotZero);
584 {
585 Label yIsNan(env);
586 Label yNotNan(env);
587 Branch(DoubleIsNAN(*doubleY), &yIsNan, &yNotNan);
588 Bind(&yIsNan);
589 Jump(&yIsZeroOrNanOrxIsNanOrInf);
590 Bind(&yNotNan);
591 {
592 Label xIsNan(env);
593 Label xNotNan(env);
594 Branch(DoubleIsNAN(*doubleX), &xIsNan, &xNotNan);
595 Bind(&xIsNan);
596 Jump(&yIsZeroOrNanOrxIsNanOrInf);
597 Bind(&xNotNan);
598 {
599 Label xIsInf(env);
600 Label xNotInf(env);
601 Branch(DoubleIsINF(*doubleX), &xIsInf, &xNotInf);
602 Bind(&xIsInf);
603 Jump(&yIsZeroOrNanOrxIsNanOrInf);
604 Bind(&xNotInf);
605 Jump(&yNeiZeroOrNanAndxNeiNanOrInf);
606 }
607 }
608 }
609 Bind(&yIsZeroOrNanOrxIsNanOrInf);
610 Return(DoubleBuildTaggedWithNoGC(GetDoubleConstant(base::NAN_VALUE)));
611 Bind(&yNeiZeroOrNanAndxNeiNanOrInf);
612 {
613 Label xIsFloatZero(env);
614 Label xIsZeroOryIsInf(env);
615 Label xNotZeroAndyNotInf(env);
616 Branch(DoubleEqual(*doubleX, GetDoubleConstant(0.0)), &xIsFloatZero, &xNotZeroAndyNotInf);
617 Bind(&xIsFloatZero);
618 Jump(&xIsZeroOryIsInf);
619 Label yIsInf(env);
620 Label yNotInf(env);
621 Bind(&xNotZeroAndyNotInf);
622 Branch(DoubleIsINF(*doubleY), &yIsInf, &yNotInf);
623 Bind(&yIsInf);
624 Jump(&xIsZeroOryIsInf);
625 Bind(&yNotInf);
626 {
627 doubleX = TaggedCastToDouble(CallRuntimeTrampoline(glue, GetInt64Constant(FAST_STUB_ID(FloatMod)), {
628 DoubleBuildTaggedTypeWithNoGC(*doubleX), DoubleBuildTaggedTypeWithNoGC(*doubleY)
629 }));
630 Return(DoubleBuildTaggedWithNoGC(*doubleX));
631 }
632 Bind(&xIsZeroOryIsInf);
633 Return(DoubleBuildTaggedWithNoGC(*doubleX));
634 }
635 }
636 }
637 }
638
GenerateCircuit(const CompilationConfig * cfg)639 void FastTypeOfStub::GenerateCircuit(const CompilationConfig *cfg)
640 {
641 Stub::GenerateCircuit(cfg);
642 auto env = GetEnvironment();
643 GateRef glue = PtrArgument(0);
644 GateRef obj = TaggedArgument(1);
645 DEFVARIABLE(holder, StubMachineType::TAGGED, obj);
646 GateRef gConstOffset = IntPtrAdd(glue, GetIntPtrConstant(env->GetGlueOffset(JSThread::GlueID::GLOBAL_CONST)));
647 GateRef booleanIndex = GetGlobalConstantString(ConstantIndex::UNDEFINED_STRING_INDEX);
648 GateRef gConstUndefindStr = Load(StubMachineType::TAGGED_POINTER, gConstOffset, booleanIndex);
649 DEFVARIABLE(resultRep, StubMachineType::TAGGED_POINTER, gConstUndefindStr);
650 Label objIsTrue(env);
651 Label objNotTrue(env);
652 Label exit(env);
653 Label defaultLabel(env);
654 GateRef gConstBooleanStr = Load(
655 StubMachineType::TAGGED_POINTER, gConstOffset, GetGlobalConstantString(ConstantIndex::BOOLEAN_STRING_INDEX));
656 Branch(Int64Equal(obj, GetInt64Constant(JSTaggedValue::VALUE_TRUE)), &objIsTrue, &objNotTrue);
657 Bind(&objIsTrue);
658 {
659 resultRep = gConstBooleanStr;
660 Jump(&exit);
661 }
662 Bind(&objNotTrue);
663 {
664 Label objIsFalse(env);
665 Label objNotFalse(env);
666 Branch(Int64Equal(obj, GetInt64Constant(JSTaggedValue::VALUE_FALSE)), &objIsFalse, &objNotFalse);
667 Bind(&objIsFalse);
668 {
669 resultRep = gConstBooleanStr;
670 Jump(&exit);
671 }
672 Bind(&objNotFalse);
673 {
674 Label objIsNull(env);
675 Label objNotNull(env);
676 Branch(Int64Equal(obj, GetInt64Constant(JSTaggedValue::VALUE_NULL)), &objIsNull, &objNotNull);
677 Bind(&objIsNull);
678 {
679 resultRep = Load(
680 StubMachineType::TAGGED_POINTER, gConstOffset,
681 GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX));
682 Jump(&exit);
683 }
684 Bind(&objNotNull);
685 {
686 Label objIsUndefined(env);
687 Label objNotUndefined(env);
688 Branch(Int64Equal(obj, GetInt64Constant(JSTaggedValue::VALUE_UNDEFINED)), &objIsUndefined,
689 &objNotUndefined);
690 Bind(&objIsUndefined);
691 {
692 resultRep = Load(StubMachineType::TAGGED_POINTER, gConstOffset,
693 GetGlobalConstantString(ConstantIndex::UNDEFINED_STRING_INDEX));
694 Jump(&exit);
695 }
696 Bind(&objNotUndefined);
697 Jump(&defaultLabel);
698 }
699 }
700 }
701 Bind(&defaultLabel);
702 {
703 Label objIsHeapObject(env);
704 Label objNotHeapObject(env);
705 Branch(TaggedIsHeapObject(obj), &objIsHeapObject, &objNotHeapObject);
706 Bind(&objIsHeapObject);
707 {
708 Label objIsString(env);
709 Label objNotString(env);
710 Branch(IsString(obj), &objIsString, &objNotString);
711 Bind(&objIsString);
712 {
713 resultRep = Load(
714 StubMachineType::TAGGED_POINTER, gConstOffset,
715 GetGlobalConstantString(ConstantIndex::STRING_STRING_INDEX));
716 Jump(&exit);
717 }
718 Bind(&objNotString);
719 {
720 Label objIsSymbol(env);
721 Label objNotSymbol(env);
722 Branch(IsSymbol(obj), &objIsSymbol, &objNotSymbol);
723 Bind(&objIsSymbol);
724 {
725 resultRep = Load(StubMachineType::TAGGED_POINTER, gConstOffset,
726 GetGlobalConstantString(ConstantIndex::SYMBOL_STRING_INDEX));
727 Jump(&exit);
728 }
729 Bind(&objNotSymbol);
730 {
731 Label objIsCallable(env);
732 Label objNotCallable(env);
733 Branch(IsCallable(obj), &objIsCallable, &objNotCallable);
734 Bind(&objIsCallable);
735 {
736 resultRep = Load(
737 StubMachineType::TAGGED_POINTER, gConstOffset,
738 GetGlobalConstantString(ConstantIndex::FUNCTION_STRING_INDEX));
739 Jump(&exit);
740 }
741 Bind(&objNotCallable);
742 {
743 resultRep = Load(
744 StubMachineType::TAGGED_POINTER, gConstOffset,
745 GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX));
746 Jump(&exit);
747 }
748 }
749 }
750 }
751 Bind(&objNotHeapObject);
752 {
753 Label objIsNum(env);
754 Label objNotNum(env);
755 Branch(TaggedIsNumber(obj), &objIsNum, &objNotNum);
756 Bind(&objIsNum);
757 {
758 resultRep = Load(
759 StubMachineType::TAGGED_POINTER, gConstOffset,
760 GetGlobalConstantString(ConstantIndex::NUMBER_STRING_INDEX));
761 Jump(&exit);
762 }
763 Bind(&objNotNum);
764 Jump(&exit);
765 }
766 }
767 Bind(&exit);
768 Return(*resultRep);
769 }
770
GenerateCircuit(const CompilationConfig * cfg)771 void FastEqualStub::GenerateCircuit(const CompilationConfig *cfg)
772 {
773 Stub::GenerateCircuit(cfg);
774 auto env = GetEnvironment();
775 GateRef x = TaggedArgument(0);
776 GateRef y = TaggedArgument(1);
777 Label xIsEqualy(env);
778 Label xIsNotEqualy(env);
779 Branch(Int64Equal(x, y), &xIsEqualy, &xIsNotEqualy);
780 Bind(&xIsEqualy);
781 {
782 Label xIsDouble(env);
783 Label xNotDoubleOrxNotNan(env);
784 Branch(TaggedIsDouble(x), &xIsDouble, &xNotDoubleOrxNotNan);
785 Bind(&xIsDouble);
786 {
787 GateRef doubleX = TaggedCastToDouble(x);
788 Label xIsNan(env);
789 Branch(DoubleIsNAN(doubleX), &xIsNan, &xNotDoubleOrxNotNan);
790 Bind(&xIsNan);
791 Return(TaggedFalse());
792 }
793 Bind(&xNotDoubleOrxNotNan);
794 Return(TaggedTrue());
795 }
796 Bind(&xIsNotEqualy);
797 {
798 Label xIsNumber(env);
799 Label xNotNumberAndxNotIntAndyNotInt(env);
800 Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberAndxNotIntAndyNotInt);
801 Bind(&xIsNumber);
802 {
803 Label xIsInt(env);
804 Branch(TaggedIsInt(x), &xIsInt, &xNotNumberAndxNotIntAndyNotInt);
805 Bind(&xIsInt);
806 {
807 Label yIsInt(env);
808 Branch(TaggedIsInt(y), &yIsInt, &xNotNumberAndxNotIntAndyNotInt);
809 Bind(&yIsInt);
810 Return(TaggedFalse());
811 }
812 }
813 Bind(&xNotNumberAndxNotIntAndyNotInt);
814 {
815 Label yIsUndefinedOrNull(env);
816 Label xyNotUndefinedAndNull(env);
817 Branch(TaggedIsUndefinedOrNull(y), &yIsUndefinedOrNull, &xyNotUndefinedAndNull);
818 Bind(&yIsUndefinedOrNull);
819 {
820 Label xIsHeapObject(env);
821 Label xNotHeapObject(env);
822 Branch(TaggedIsHeapObject(x), &xIsHeapObject, &xNotHeapObject);
823 Bind(&xIsHeapObject);
824 Return(TaggedFalse());
825 Bind(&xNotHeapObject);
826 {
827 Label xIsUndefinedOrNull(env);
828 Branch(TaggedIsUndefinedOrNull(x), &xIsUndefinedOrNull, &xyNotUndefinedAndNull);
829 Bind(&xIsUndefinedOrNull);
830 Return(TaggedTrue());
831 }
832 }
833 Bind(&xyNotUndefinedAndNull);
834 {
835 Label xIsBoolean(env);
836 Label xNotBooleanAndyNotSpecial(env);
837 Branch(TaggedIsBoolean(x), &xIsBoolean, &xNotBooleanAndyNotSpecial);
838 Bind(&xIsBoolean);
839 {
840 Label yIsSpecial(env);
841 Branch(TaggedIsSpecial(y), &yIsSpecial, &xNotBooleanAndyNotSpecial);
842 Bind(&yIsSpecial);
843 Return(TaggedFalse());
844 }
845 Bind(&xNotBooleanAndyNotSpecial);
846 {
847 Return(GetHoleConstant(StubMachineType::UINT64));
848 }
849 }
850 }
851 }
852 }
853
GenerateCircuit(const CompilationConfig * cfg)854 void GetPropertyByIndexStub::GenerateCircuit(const CompilationConfig *cfg)
855 {
856 Stub::GenerateCircuit(cfg);
857 GateRef glue = PtrArgument(0);
858 GateRef receiver = TaggedArgument(1);
859 GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */
860 Return(GetPropertyByIndex(glue, receiver, index));
861 }
862
GenerateCircuit(const CompilationConfig * cfg)863 void SetPropertyByIndexStub::GenerateCircuit(const CompilationConfig *cfg)
864 {
865 Stub::GenerateCircuit(cfg);
866 GateRef glue = PtrArgument(0);
867 GateRef receiver = TaggedArgument(1);
868 GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */
869 GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */
870 Return(SetPropertyByIndex(glue, receiver, index, value));
871 }
872
GenerateCircuit(const CompilationConfig * cfg)873 void GetPropertyByNameStub::GenerateCircuit(const CompilationConfig *cfg)
874 {
875 Stub::GenerateCircuit(cfg);
876 GateRef glue = PtrArgument(0);
877 GateRef receiver = TaggedArgument(1);
878 GateRef key = TaggedArgument(2); // 2 : 3rd para
879 Return(GetPropertyByName(glue, receiver, key));
880 }
881
GenerateCircuit(const CompilationConfig * cfg)882 void SetPropertyByNameStub::GenerateCircuit(const CompilationConfig *cfg)
883 {
884 Stub::GenerateCircuit(cfg);
885 GateRef glue = PtrArgument(0);
886 GateRef receiver = TaggedArgument(1);
887 GateRef key = TaggedArgument(2); // 2 : 3rd para
888 GateRef value = TaggedArgument(3); // 3 : 4th para
889 Return(SetPropertyByName(glue, receiver, key, value));
890 }
891
GenerateCircuit(const CompilationConfig * cfg)892 void SetPropertyByNameWithOwnStub::GenerateCircuit(const CompilationConfig *cfg)
893 {
894 Stub::GenerateCircuit(cfg);
895 GateRef glue = PtrArgument(0);
896 GateRef receiver = TaggedArgument(1);
897 GateRef key = TaggedArgument(2); // 2 : 3rd para
898 GateRef value = TaggedArgument(3); // 3 : 4th para
899 Return(SetPropertyByNameWithOwn(glue, receiver, key, value));
900 }
901
GenerateCircuit(const CompilationConfig * cfg)902 void GetPropertyByValueStub::GenerateCircuit(const CompilationConfig *cfg)
903 {
904 Stub::GenerateCircuit(cfg);
905 auto env = GetEnvironment();
906 GateRef glue = PtrArgument(0);
907 GateRef receiver = TaggedArgument(1);
908 DEFVARIABLE(key, StubMachineType::TAGGED, TaggedArgument(2)); /* 2 : 3rd parameter is key */
909
910 Label isNumberOrStringSymbol(env);
911 Label notNumber(env);
912 Label isStringOrSymbol(env);
913 Label notStringOrSymbol(env);
914 Label exit(env);
915
916 Branch(TaggedIsNumber(*key), &isNumberOrStringSymbol, ¬Number);
917 Bind(¬Number);
918 {
919 Branch(TaggedIsStringOrSymbol(*key), &isNumberOrStringSymbol, ¬StringOrSymbol);
920 Bind(¬StringOrSymbol);
921 {
922 Return(GetHoleConstant());
923 }
924 }
925 Bind(&isNumberOrStringSymbol);
926 {
927 GateRef index = TryToElementsIndex(*key);
928 Label validIndex(env);
929 Label notValidIndex(env);
930 Branch(Int32GreaterThanOrEqual(index, GetInt32Constant(0)), &validIndex, ¬ValidIndex);
931 Bind(&validIndex);
932 {
933 Return(GetPropertyByIndex(glue, receiver, index));
934 }
935 Bind(¬ValidIndex);
936 {
937 Label notNumber(env);
938 Label getByName(env);
939 Branch(TaggedIsNumber(*key), &exit, ¬Number);
940 Bind(¬Number);
941 {
942 Label isString(env);
943 Label notString(env);
944 Label isInternalString(env);
945 Label notIntenalString(env);
946 Branch(TaggedIsString(*key), &isString, ¬String);
947 Bind(&isString);
948 {
949 Branch(IsInternalString(*key), &isInternalString, ¬IntenalString);
950 Bind(&isInternalString);
951 Jump(&getByName);
952 Bind(¬IntenalString);
953 {
954 key = CallRuntimeTrampoline(glue,
955 GetInt64Constant(FAST_STUB_ID(NewInternalString)), { *key });
956 Jump(&getByName);
957 }
958 }
959 Bind(¬String);
960 {
961 Jump(&getByName);
962 }
963 }
964 Bind(&getByName);
965 {
966 Return(GetPropertyByName(glue, receiver, *key));
967 }
968 }
969 }
970 Bind(&exit);
971 Return(GetHoleConstant());
972 }
973
GenerateCircuit(const CompilationConfig * cfg)974 void SetPropertyByValueStub::GenerateCircuit(const CompilationConfig *cfg)
975 {
976 Stub::GenerateCircuit(cfg);
977 auto env = GetEnvironment();
978 GateRef glue = PtrArgument(0);
979 GateRef receiver = TaggedArgument(1);
980 DEFVARIABLE(key, StubMachineType::TAGGED, TaggedArgument(2)); /* 2 : 3rd parameter is key */
981 GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */
982
983 Label isNumberOrStringSymbol(env);
984 Label notNumber(env);
985 Label isStringOrSymbol(env);
986 Label notStringOrSymbol(env);
987 Label exit(env);
988
989 Branch(TaggedIsNumber(*key), &isNumberOrStringSymbol, ¬Number);
990 Bind(¬Number);
991 {
992 Branch(TaggedIsStringOrSymbol(*key), &isNumberOrStringSymbol, ¬StringOrSymbol);
993 Bind(¬StringOrSymbol);
994 {
995 Return(GetHoleConstant(StubMachineType::UINT64));
996 }
997 }
998 Bind(&isNumberOrStringSymbol);
999 {
1000 GateRef index = TryToElementsIndex(*key);
1001 Label validIndex(env);
1002 Label notValidIndex(env);
1003 Branch(Int32GreaterThanOrEqual(index, GetInt32Constant(0)), &validIndex, ¬ValidIndex);
1004 Bind(&validIndex);
1005 {
1006 Return(SetPropertyByIndex(glue, receiver, index, value));
1007 }
1008 Bind(¬ValidIndex);
1009 {
1010 Label notNumber(env);
1011 Label getByName(env);
1012 Branch(TaggedIsNumber(*key), &exit, ¬Number);
1013 Bind(¬Number);
1014 {
1015 Label isString(env);
1016 Label notString(env);
1017 Label isInternalString(env);
1018 Label notIntenalString(env);
1019 Branch(TaggedIsString(*key), &isString, ¬String);
1020 Bind(&isString);
1021 {
1022 Branch(IsInternalString(*key), &isInternalString, ¬IntenalString);
1023 Bind(&isInternalString);
1024 Jump(&getByName);
1025 Bind(¬IntenalString);
1026 {
1027 key = CallRuntimeTrampoline(glue,
1028 GetInt64Constant(FAST_STUB_ID(NewInternalString)), { *key });
1029 Jump(&getByName);
1030 }
1031 }
1032 Bind(¬String);
1033 {
1034 Jump(&getByName);
1035 }
1036 }
1037 Bind(&getByName);
1038 {
1039 Return(SetPropertyByName(glue, receiver, *key, value));
1040 }
1041 }
1042 }
1043 Bind(&exit);
1044 Return(GetHoleConstant(StubMachineType::UINT64));
1045 }
1046
GenerateCircuit(const CompilationConfig * cfg)1047 void TryLoadICByNameStub::GenerateCircuit(const CompilationConfig *cfg)
1048 {
1049 Stub::GenerateCircuit(cfg);
1050 auto env = GetEnvironment();
1051 GateRef glue = PtrArgument(0);
1052 GateRef receiver = TaggedArgument(1);
1053 GateRef firstValue = TaggedArgument(2); /* 2 : 3rd parameter is value */
1054 GateRef secondValue = TaggedArgument(3); /* 3 : 4th parameter is value */
1055
1056 Label receiverIsHeapObject(env);
1057 Label receiverNotHeapObject(env);
1058 Label hclassEqualFirstValue(env);
1059 Label hclassNotEqualFirstValue(env);
1060 Label cachedHandlerNotHole(env);
1061 Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
1062 Bind(&receiverIsHeapObject);
1063 {
1064 GateRef hclass = LoadHClass(receiver);
1065 Branch(Int64Equal(TaggedCastToWeakReferentUnChecked(firstValue), hclass),
1066 &hclassEqualFirstValue, &hclassNotEqualFirstValue);
1067 Bind(&hclassEqualFirstValue);
1068 {
1069 Return(LoadICWithHandler(glue, receiver, receiver, secondValue));
1070 }
1071 Bind(&hclassNotEqualFirstValue);
1072 {
1073 GateRef cachedHandler = CheckPolyHClass(firstValue, hclass);
1074 Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
1075 Bind(&cachedHandlerNotHole);
1076 {
1077 Return(LoadICWithHandler(glue, receiver, receiver, cachedHandler));
1078 }
1079 }
1080 }
1081 Bind(&receiverNotHeapObject);
1082 {
1083 Return(GetHoleConstant());
1084 }
1085 }
1086
GenerateCircuit(const CompilationConfig * cfg)1087 void TryLoadICByValueStub::GenerateCircuit(const CompilationConfig *cfg)
1088 {
1089 Stub::GenerateCircuit(cfg);
1090 auto env = GetEnvironment();
1091 GateRef glue = PtrArgument(0);
1092 GateRef receiver = TaggedArgument(1);
1093 GateRef key = TaggedArgument(2); /* 2 : 3rd parameter is value */
1094 GateRef firstValue = TaggedArgument(3); /* 3 : 4th parameter is value */
1095 GateRef secondValue = TaggedArgument(4); /* 4 : 5th parameter is value */
1096
1097 Label receiverIsHeapObject(env);
1098 Label receiverNotHeapObject(env);
1099 Label hclassEqualFirstValue(env);
1100 Label hclassNotEqualFirstValue(env);
1101 Label firstValueEqualKey(env);
1102 Label cachedHandlerNotHole(env);
1103 Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
1104 Bind(&receiverIsHeapObject);
1105 {
1106 GateRef hclass = LoadHClass(receiver);
1107 Branch(Int64Equal(TaggedCastToWeakReferentUnChecked(firstValue), hclass),
1108 &hclassEqualFirstValue, &hclassNotEqualFirstValue);
1109 Bind(&hclassEqualFirstValue);
1110 Return(LoadElement(receiver, key));
1111 Bind(&hclassNotEqualFirstValue);
1112 {
1113 Branch(Int64Equal(firstValue, key), &firstValueEqualKey, &receiverNotHeapObject);
1114 Bind(&firstValueEqualKey);
1115 {
1116 auto cachedHandler = CheckPolyHClass(secondValue, hclass);
1117 Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
1118 Bind(&cachedHandlerNotHole);
1119 Return(LoadICWithHandler(glue, receiver, receiver, cachedHandler));
1120 }
1121 }
1122 }
1123 Bind(&receiverNotHeapObject);
1124 Return(GetHoleConstant());
1125 }
1126
GenerateCircuit(const CompilationConfig * cfg)1127 void TryStoreICByNameStub::GenerateCircuit(const CompilationConfig *cfg)
1128 {
1129 Stub::GenerateCircuit(cfg);
1130 auto env = GetEnvironment();
1131 GateRef glue = PtrArgument(0);
1132 GateRef receiver = TaggedArgument(1);
1133 GateRef firstValue = TaggedArgument(2); /* 2 : 3rd parameter is value */
1134 GateRef secondValue = TaggedArgument(3); /* 3 : 4th parameter is value */
1135 GateRef value = TaggedArgument(4); /* 4 : 5th parameter is value */
1136 Label receiverIsHeapObject(env);
1137 Label receiverNotHeapObject(env);
1138 Label hclassEqualFirstValue(env);
1139 Label hclassNotEqualFirstValue(env);
1140 Label cachedHandlerNotHole(env);
1141 Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
1142 Bind(&receiverIsHeapObject);
1143 {
1144 GateRef hclass = LoadHClass(receiver);
1145 Branch(Int64Equal(TaggedCastToWeakReferentUnChecked(firstValue), hclass),
1146 &hclassEqualFirstValue, &hclassNotEqualFirstValue);
1147 Bind(&hclassEqualFirstValue);
1148 {
1149 Return(StoreICWithHandler(glue, receiver, receiver, value, secondValue));
1150 }
1151 Bind(&hclassNotEqualFirstValue);
1152 {
1153 GateRef cachedHandler = CheckPolyHClass(firstValue, hclass);
1154 Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
1155 Bind(&cachedHandlerNotHole);
1156 {
1157 Return(StoreICWithHandler(glue, receiver, receiver, value, cachedHandler));
1158 }
1159 }
1160 }
1161 Bind(&receiverNotHeapObject);
1162 Return(GetHoleConstant(StubMachineType::UINT64));
1163 }
1164
GenerateCircuit(const CompilationConfig * cfg)1165 void TryStoreICByValueStub::GenerateCircuit(const CompilationConfig *cfg)
1166 {
1167 Stub::GenerateCircuit(cfg);
1168 auto env = GetEnvironment();
1169 GateRef glue = PtrArgument(0);
1170 GateRef receiver = TaggedArgument(1);
1171 GateRef key = TaggedArgument(2); /* 2 : 3rd parameter is value */
1172 GateRef firstValue = TaggedArgument(3); /* 3 : 4th parameter is value */
1173 GateRef secondValue = TaggedArgument(4); /* 4 : 5th parameter is value */
1174 GateRef value = TaggedArgument(5); /* 5 : 6th parameter is value */
1175 Label receiverIsHeapObject(env);
1176 Label receiverNotHeapObject(env);
1177 Label hclassEqualFirstValue(env);
1178 Label hclassNotEqualFirstValue(env);
1179 Label firstValueEqualKey(env);
1180 Label cachedHandlerNotHole(env);
1181 Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
1182 Bind(&receiverIsHeapObject);
1183 {
1184 GateRef hclass = LoadHClass(receiver);
1185 Branch(Int64Equal(TaggedCastToWeakReferentUnChecked(firstValue), hclass),
1186 &hclassEqualFirstValue, &hclassNotEqualFirstValue);
1187 Bind(&hclassEqualFirstValue);
1188 Return(ICStoreElement(glue, receiver, key, value, secondValue));
1189 Bind(&hclassNotEqualFirstValue);
1190 {
1191 Branch(Int64Equal(firstValue, key), &firstValueEqualKey, &receiverNotHeapObject);
1192 Bind(&firstValueEqualKey);
1193 {
1194 GateRef cachedHandler = CheckPolyHClass(secondValue, hclass);
1195 Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
1196 Bind(&cachedHandlerNotHole);
1197 Return(StoreICWithHandler(glue, receiver, receiver, value, cachedHandler));
1198 }
1199 }
1200 }
1201 Bind(&receiverNotHeapObject);
1202 Return(GetHoleConstant(StubMachineType::UINT64));
1203 }
1204
GenerateCircuit(const CompilationConfig * cfg)1205 void TestAbsoluteAddressRelocationStub::GenerateCircuit(const CompilationConfig *cfg)
1206 {
1207 Stub::GenerateCircuit(cfg);
1208 auto env = GetEnvironment();
1209 GateRef a = Int64Argument(0);
1210 GateRef b = Int64Argument(1);
1211 Label start(env);
1212 Jump(&start);
1213 Bind(&start);
1214 GateRef globalValueC = GetRelocatableData(0xabc);
1215 GateRef globalValueD = GetRelocatableData(0xbcd);
1216 GateRef dummyValueC = Load(StubMachineType::INT64, globalValueC);
1217 GateRef dummyValueD = Load(StubMachineType::INT64, globalValueD);
1218 // Load from same relocatable data twice to see if it breaks constant fold opt. Result shows it doesn't.
1219 GateRef dummyValueC1 = Load(StubMachineType::INT64, globalValueC);
1220 GateRef result = Int64Add(a, Int64Add(b, Int64Add(dummyValueC, Int64Add(dummyValueD, dummyValueC1))));
1221 Return(result);
1222 }
1223 } // namespace panda::ecmascript::kungfu
1224