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
16 #include "ecmascript/compiler/operations_stub_builder.h"
17 #include "ecmascript/compiler/interpreter_stub-inl.h"
18 #include "ecmascript/compiler/rt_call_signature.h"
19 #include "ecmascript/compiler/stub_builder-inl.h"
20
21 namespace panda::ecmascript::kungfu {
Equal(GateRef glue,GateRef left,GateRef right)22 GateRef OperationsStubBuilder::Equal(GateRef glue, GateRef left, GateRef right)
23 {
24 auto env = GetEnvironment();
25 Label entry(env);
26 env->SubCfgEntry(&entry);
27 Label exit(env);
28 Label isHole(env);
29 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
30 result = FastEqual(left, right);
31 Branch(TaggedIsHole(*result), &isHole, &exit);
32 Bind(&isHole);
33 {
34 // slow path
35 result = CallRuntime(glue, RTSTUB_ID(Eq), { left, right });
36 Jump(&exit);
37 }
38 Bind(&exit);
39 auto ret = *result;
40 env->SubCfgExit();
41 return ret;
42 }
43
NotEqual(GateRef glue,GateRef left,GateRef right)44 GateRef OperationsStubBuilder::NotEqual(GateRef glue, GateRef left, GateRef right)
45 {
46 auto env = GetEnvironment();
47 Label entry(env);
48 env->SubCfgEntry(&entry);
49 Label exit(env);
50
51 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
52 result = FastEqual(left, right);
53 Label isHole(env);
54 Label notHole(env);
55 Branch(TaggedIsHole(*result), &isHole, ¬Hole);
56 Bind(&isHole);
57 {
58 // slow path
59 result = CallRuntime(glue, RTSTUB_ID(NotEq), { left, right });
60 Jump(&exit);
61 }
62 Bind(¬Hole);
63 {
64 Label resultIsTrue(env);
65 Label resultNotTrue(env);
66 Branch(TaggedIsTrue(*result), &resultIsTrue, &resultNotTrue);
67 Bind(&resultIsTrue);
68 {
69 result = TaggedFalse();
70 Jump(&exit);
71 }
72 Bind(&resultNotTrue);
73 {
74 result = TaggedTrue();
75 Jump(&exit);
76 }
77 }
78 Bind(&exit);
79 auto ret = *result;
80 env->SubCfgExit();
81 return ret;
82 }
83
Less(GateRef glue,GateRef left,GateRef right)84 GateRef OperationsStubBuilder::Less(GateRef glue, GateRef left, GateRef right)
85 {
86 auto env = GetEnvironment();
87 Label entry(env);
88 env->SubCfgEntry(&entry);
89 Label exit(env);
90 Label leftIsInt(env);
91 Label leftOrRightNotInt(env);
92 Label leftLessRight(env);
93 Label leftNotLessRight(env);
94 Label slowPath(env);
95
96 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
97 Branch(TaggedIsInt(left), &leftIsInt, &leftOrRightNotInt);
98 Bind(&leftIsInt);
99 {
100 Label rightIsInt(env);
101 Branch(TaggedIsInt(right), &rightIsInt, &leftOrRightNotInt);
102 Bind(&rightIsInt);
103 {
104 GateRef intLeft = TaggedGetInt(left);
105 GateRef intRight = TaggedGetInt(right);
106 Branch(Int32LessThan(intLeft, intRight), &leftLessRight, &leftNotLessRight);
107 }
108 }
109 Bind(&leftOrRightNotInt);
110 {
111 Label leftIsNumber(env);
112 Branch(TaggedIsNumber(left), &leftIsNumber, &slowPath);
113 Bind(&leftIsNumber);
114 {
115 Label rightIsNumber(env);
116 Branch(TaggedIsNumber(right), &rightIsNumber, &slowPath);
117 Bind(&rightIsNumber);
118 {
119 // fast path
120 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
121 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
122 Label leftIsInt1(env);
123 Label leftNotInt1(env);
124 Label exit1(env);
125 Label exit2(env);
126 Label rightIsInt1(env);
127 Label rightNotInt1(env);
128 Branch(TaggedIsInt(left), &leftIsInt1, &leftNotInt1);
129 Bind(&leftIsInt1);
130 {
131 doubleLeft = ChangeInt32ToFloat64(TaggedGetInt(left));
132 Jump(&exit1);
133 }
134 Bind(&leftNotInt1);
135 {
136 doubleLeft = GetDoubleOfTDouble(left);
137 Jump(&exit1);
138 }
139 Bind(&exit1);
140 {
141 Branch(TaggedIsInt(right), &rightIsInt1, &rightNotInt1);
142 }
143 Bind(&rightIsInt1);
144 {
145 doubleRight = ChangeInt32ToFloat64(TaggedGetInt(right));
146 Jump(&exit2);
147 }
148 Bind(&rightNotInt1);
149 {
150 doubleRight = GetDoubleOfTDouble(right);
151 Jump(&exit2);
152 }
153 Bind(&exit2);
154 {
155 Branch(DoubleLessThan(*doubleLeft, *doubleRight), &leftLessRight, &leftNotLessRight);
156 }
157 }
158 }
159 }
160 Bind(&leftLessRight);
161 {
162 result = TaggedTrue();
163 Jump(&exit);
164 }
165 Bind(&leftNotLessRight);
166 {
167 result = TaggedFalse();
168 Jump(&exit);
169 }
170 Bind(&slowPath);
171 {
172 result = CallRuntime(glue, RTSTUB_ID(Less), { left, right });
173 Jump(&exit);
174 }
175 Bind(&exit);
176 auto ret = *result;
177 env->SubCfgExit();
178 return ret;
179 }
180
LessEq(GateRef glue,GateRef left,GateRef right)181 GateRef OperationsStubBuilder::LessEq(GateRef glue, GateRef left, GateRef right)
182 {
183 auto env = GetEnvironment();
184 Label entry(env);
185 env->SubCfgEntry(&entry);
186 Label exit(env);
187 Label leftIsInt(env);
188 Label leftOrRightNotInt(env);
189 Label leftLessEqRight(env);
190 Label leftNotLessEqRight(env);
191 Label slowPath(env);
192
193 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
194 Branch(TaggedIsInt(left), &leftIsInt, &leftOrRightNotInt);
195 Bind(&leftIsInt);
196 {
197 Label rightIsInt(env);
198 Branch(TaggedIsInt(right), &rightIsInt, &leftOrRightNotInt);
199 Bind(&rightIsInt);
200 {
201 GateRef intLeft = TaggedGetInt(left);
202 GateRef intRight = TaggedGetInt(right);
203 Branch(Int32LessThanOrEqual(intLeft, intRight), &leftLessEqRight, &leftNotLessEqRight);
204 }
205 }
206 Bind(&leftOrRightNotInt);
207 {
208 Label leftIsNumber(env);
209 Branch(TaggedIsNumber(left), &leftIsNumber, &slowPath);
210 Bind(&leftIsNumber);
211 {
212 Label rightIsNumber(env);
213 Branch(TaggedIsNumber(right), &rightIsNumber, &slowPath);
214 Bind(&rightIsNumber);
215 {
216 // fast path
217 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
218 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
219 Label leftIsInt1(env);
220 Label leftNotInt1(env);
221 Label exit1(env);
222 Label exit2(env);
223 Label rightIsInt1(env);
224 Label rightNotInt1(env);
225 Branch(TaggedIsInt(left), &leftIsInt1, &leftNotInt1);
226 Bind(&leftIsInt1);
227 {
228 doubleLeft = ChangeInt32ToFloat64(TaggedGetInt(left));
229 Jump(&exit1);
230 }
231 Bind(&leftNotInt1);
232 {
233 doubleLeft = GetDoubleOfTDouble(left);
234 Jump(&exit1);
235 }
236 Bind(&exit1);
237 {
238 Branch(TaggedIsInt(right), &rightIsInt1, &rightNotInt1);
239 }
240 Bind(&rightIsInt1);
241 {
242 doubleRight = ChangeInt32ToFloat64(TaggedGetInt(right));
243 Jump(&exit2);
244 }
245 Bind(&rightNotInt1);
246 {
247 doubleRight = GetDoubleOfTDouble(right);
248 Jump(&exit2);
249 }
250 Bind(&exit2);
251 {
252 Branch(DoubleLessThanOrEqual(*doubleLeft, *doubleRight), &leftLessEqRight, &leftNotLessEqRight);
253 }
254 }
255 }
256 }
257 Bind(&leftLessEqRight);
258 {
259 result = TaggedTrue();
260 Jump(&exit);
261 }
262 Bind(&leftNotLessEqRight);
263 {
264 result = TaggedFalse();
265 Jump(&exit);
266 }
267 Bind(&slowPath);
268 {
269 result = CallRuntime(glue, RTSTUB_ID(LessEq), { left, right });
270 Jump(&exit);
271 }
272 Bind(&exit);
273 auto ret = *result;
274 env->SubCfgExit();
275 return ret;
276 }
277
Greater(GateRef glue,GateRef left,GateRef right)278 GateRef OperationsStubBuilder::Greater(GateRef glue, GateRef left, GateRef right)
279 {
280 auto env = GetEnvironment();
281 Label entry(env);
282 env->SubCfgEntry(&entry);
283 Label exit(env);
284 Label leftIsInt(env);
285 Label leftOrRightNotInt(env);
286 Label leftGreaterRight(env);
287 Label leftNotGreaterRight(env);
288 Label slowPath(env);
289 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
290 Branch(TaggedIsInt(left), &leftIsInt, &leftOrRightNotInt);
291 Bind(&leftIsInt);
292 {
293 Label rightIsInt(env);
294 Branch(TaggedIsInt(right), &rightIsInt, &leftOrRightNotInt);
295 Bind(&rightIsInt);
296 {
297 GateRef intLeft = TaggedGetInt(left);
298 GateRef intRight = TaggedGetInt(right);
299 Branch(Int32GreaterThan(intLeft, intRight), &leftGreaterRight, &leftNotGreaterRight);
300 }
301 }
302 Bind(&leftOrRightNotInt);
303 {
304 Label leftIsNumber(env);
305 Branch(TaggedIsNumber(left), &leftIsNumber, &slowPath);
306 Bind(&leftIsNumber);
307 {
308 Label rightIsNumber(env);
309 Branch(TaggedIsNumber(right), &rightIsNumber, &slowPath);
310 Bind(&rightIsNumber);
311 {
312 // fast path
313 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
314 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
315 Label leftIsInt1(env);
316 Label leftNotInt1(env);
317 Label exit1(env);
318 Label exit2(env);
319 Label rightIsInt1(env);
320 Label rightNotInt1(env);
321 Branch(TaggedIsInt(left), &leftIsInt1, &leftNotInt1);
322 Bind(&leftIsInt1);
323 {
324 doubleLeft = ChangeInt32ToFloat64(TaggedGetInt(left));
325 Jump(&exit1);
326 }
327 Bind(&leftNotInt1);
328 {
329 doubleLeft = GetDoubleOfTDouble(left);
330 Jump(&exit1);
331 }
332 Bind(&exit1);
333 {
334 Branch(TaggedIsInt(right), &rightIsInt1, &rightNotInt1);
335 }
336 Bind(&rightIsInt1);
337 {
338 doubleRight = ChangeInt32ToFloat64(TaggedGetInt(right));
339 Jump(&exit2);
340 }
341 Bind(&rightNotInt1);
342 {
343 doubleRight = GetDoubleOfTDouble(right);
344 Jump(&exit2);
345 }
346 Bind(&exit2);
347 {
348 Branch(DoubleGreaterThan(*doubleLeft, *doubleRight), &leftGreaterRight, &leftNotGreaterRight);
349 }
350 }
351 }
352 }
353 Bind(&leftGreaterRight);
354 {
355 result = TaggedTrue();
356 Jump(&exit);
357 }
358 Bind(&leftNotGreaterRight);
359 {
360 result = TaggedFalse();
361 Jump(&exit);
362 }
363 Bind(&slowPath);
364 {
365 result = CallRuntime(glue, RTSTUB_ID(Greater), { left, right });
366 Jump(&exit);
367 }
368 Bind(&exit);
369 auto ret = *result;
370 env->SubCfgExit();
371 return ret;
372 }
373
GreaterEq(GateRef glue,GateRef left,GateRef right)374 GateRef OperationsStubBuilder::GreaterEq(GateRef glue, GateRef left, GateRef right)
375 {
376 auto env = GetEnvironment();
377 Label entry(env);
378 env->SubCfgEntry(&entry);
379 Label exit(env);
380 Label leftIsInt(env);
381 Label leftOrRightNotInt(env);
382 Label leftGreaterEqRight(env);
383 Label leftNotGreaterEQRight(env);
384 Label slowPath(env);
385 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
386 Branch(TaggedIsInt(left), &leftIsInt, &leftOrRightNotInt);
387 Bind(&leftIsInt);
388 {
389 Label rightIsInt(env);
390 Branch(TaggedIsInt(right), &rightIsInt, &leftOrRightNotInt);
391 Bind(&rightIsInt);
392 {
393 GateRef intLeft = TaggedGetInt(left);
394 GateRef intRight = TaggedGetInt(right);
395 Branch(Int32GreaterThanOrEqual(intLeft, intRight), &leftGreaterEqRight, &leftNotGreaterEQRight);
396 }
397 }
398 Bind(&leftOrRightNotInt);
399 {
400 Label leftIsNumber(env);
401 Branch(TaggedIsNumber(left), &leftIsNumber, &slowPath);
402 Bind(&leftIsNumber);
403 {
404 Label rightIsNumber(env);
405 Branch(TaggedIsNumber(right), &rightIsNumber, &slowPath);
406 Bind(&rightIsNumber);
407 {
408 // fast path
409 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
410 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
411 Label leftIsInt1(env);
412 Label leftNotInt1(env);
413 Label exit1(env);
414 Label exit2(env);
415 Label rightIsInt1(env);
416 Label rightNotInt1(env);
417 Branch(TaggedIsInt(left), &leftIsInt1, &leftNotInt1);
418 Bind(&leftIsInt1);
419 {
420 doubleLeft = ChangeInt32ToFloat64(TaggedGetInt(left));
421 Jump(&exit1);
422 }
423 Bind(&leftNotInt1);
424 {
425 doubleLeft = GetDoubleOfTDouble(left);
426 Jump(&exit1);
427 }
428 Bind(&exit1);
429 {
430 Branch(TaggedIsInt(right), &rightIsInt1, &rightNotInt1);
431 }
432 Bind(&rightIsInt1);
433 {
434 doubleRight = ChangeInt32ToFloat64(TaggedGetInt(right));
435 Jump(&exit2);
436 }
437 Bind(&rightNotInt1);
438 {
439 doubleRight = GetDoubleOfTDouble(right);
440 Jump(&exit2);
441 }
442 Bind(&exit2);
443 {
444 Branch(DoubleGreaterThanOrEqual(*doubleLeft, *doubleRight),
445 &leftGreaterEqRight, &leftNotGreaterEQRight);
446 }
447 }
448 }
449 }
450 Bind(&leftGreaterEqRight);
451 {
452 result = TaggedTrue();
453 Jump(&exit);
454 }
455 Bind(&leftNotGreaterEQRight);
456 {
457 result = TaggedFalse();
458 Jump(&exit);
459 }
460 Bind(&slowPath);
461 {
462 result = CallRuntime(glue, RTSTUB_ID(GreaterEq), { left, right });
463 Jump(&exit);
464 }
465 Bind(&exit);
466 auto ret = *result;
467 env->SubCfgExit();
468 return ret;
469 }
470
Add(GateRef glue,GateRef left,GateRef right)471 GateRef OperationsStubBuilder::Add(GateRef glue, GateRef left, GateRef right)
472 {
473 auto env = GetEnvironment();
474 Label entry(env);
475 env->SubCfgEntry(&entry);
476 Label exit(env);
477 Label slowPath(env);
478 DEFVARIABLE(result, VariableType::JS_ANY(), FastAdd(left, right));
479 Branch(TaggedIsHole(*result), &slowPath, &exit);
480 Bind(&slowPath);
481 {
482 result = CallRuntime(glue, RTSTUB_ID(Add2), { left, right });
483 Jump(&exit);
484 }
485 Bind(&exit);
486 auto ret = *result;
487 env->SubCfgExit();
488 return ret;
489 }
490
Sub(GateRef glue,GateRef left,GateRef right)491 GateRef OperationsStubBuilder::Sub(GateRef glue, GateRef left, GateRef right)
492 {
493 auto env = GetEnvironment();
494 Label entry(env);
495 env->SubCfgEntry(&entry);
496 Label exit(env);
497 Label slowPath(env);
498 DEFVARIABLE(result, VariableType::JS_ANY(), FastSub(left, right));
499 Branch(TaggedIsHole(*result), &slowPath, &exit);
500 Bind(&slowPath);
501 {
502 result = CallRuntime(glue, RTSTUB_ID(Sub2), { left, right });
503 Jump(&exit);
504 }
505 Bind(&exit);
506 auto ret = *result;
507 env->SubCfgExit();
508 return ret;
509 }
510
Mul(GateRef glue,GateRef left,GateRef right)511 GateRef OperationsStubBuilder::Mul(GateRef glue, GateRef left, GateRef right)
512 {
513 auto env = GetEnvironment();
514 Label entry(env);
515 env->SubCfgEntry(&entry);
516 Label exit(env);
517 Label slowPath(env);
518 DEFVARIABLE(result, VariableType::JS_ANY(), FastMul(left, right));
519 Branch(TaggedIsHole(*result), &slowPath, &exit);
520 Bind(&slowPath);
521 {
522 result = CallRuntime(glue, RTSTUB_ID(Mul2), { left, right });
523 Jump(&exit);
524 }
525 Bind(&exit);
526 auto ret = *result;
527 env->SubCfgExit();
528 return ret;
529 }
530
Div(GateRef glue,GateRef left,GateRef right)531 GateRef OperationsStubBuilder::Div(GateRef glue, GateRef left, GateRef right)
532 {
533 auto env = GetEnvironment();
534 Label entry(env);
535 env->SubCfgEntry(&entry);
536 Label exit(env);
537 Label slowPath(env);
538 DEFVARIABLE(result, VariableType::JS_ANY(), FastDiv(left, right));
539 Branch(TaggedIsHole(*result), &slowPath, &exit);
540 Bind(&slowPath);
541 {
542 result = CallRuntime(glue, RTSTUB_ID(Div2), { left, right });
543 Jump(&exit);
544 }
545 Bind(&exit);
546 auto ret = *result;
547 env->SubCfgExit();
548 return ret;
549 }
550
Mod(GateRef glue,GateRef left,GateRef right)551 GateRef OperationsStubBuilder::Mod(GateRef glue, GateRef left, GateRef right)
552 {
553 auto env = GetEnvironment();
554 Label entry(env);
555 env->SubCfgEntry(&entry);
556 Label exit(env);
557 Label slowPath(env);
558 DEFVARIABLE(result, VariableType::JS_ANY(), FastMod(glue, left, right));
559 Branch(TaggedIsHole(*result), &slowPath, &exit);
560 Bind(&slowPath);
561 {
562 result = CallRuntime(glue, RTSTUB_ID(Mod2), { left, right });
563 Jump(&exit);
564 }
565 Bind(&exit);
566 auto ret = *result;
567 env->SubCfgExit();
568 return ret;
569 }
570
Shl(GateRef glue,GateRef left,GateRef right)571 GateRef OperationsStubBuilder::Shl(GateRef glue, GateRef left, GateRef right)
572 {
573 auto env = GetEnvironment();
574 Label entry(env);
575 env->SubCfgEntry(&entry);
576 Label exit(env);
577
578 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
579 DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0));
580 DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0));
581
582 Label calculate(env);
583 Label leftIsNumber(env);
584 Label leftNotNumberOrRightNotNumber(env);
585 Branch(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
586 Bind(&leftIsNumber);
587 {
588 Label rightIsNumber(env);
589 Branch(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
590 Bind(&rightIsNumber);
591 {
592 Label leftIsInt(env);
593 Label leftIsDouble(env);
594 Branch(TaggedIsInt(left), &leftIsInt, &leftIsDouble);
595 Bind(&leftIsInt);
596 {
597 Label rightIsInt(env);
598 Label rightIsDouble(env);
599 Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
600 Bind(&rightIsInt);
601 {
602 opNumber0 = GetInt32OfTInt(left);
603 opNumber1 = GetInt32OfTInt(right);
604 Jump(&calculate);
605 }
606 Bind(&rightIsDouble);
607 {
608 GateRef rightDouble = GetDoubleOfTDouble(right);
609 opNumber0 = GetInt32OfTInt(left);
610 opNumber1 = DoubleToInt(glue, rightDouble);
611 Jump(&calculate);
612 }
613 }
614 Bind(&leftIsDouble);
615 {
616 Label rightIsInt(env);
617 Label rightIsDouble(env);
618 Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
619 Bind(&rightIsInt);
620 {
621 GateRef leftDouble = GetDoubleOfTDouble(left);
622 opNumber0 = DoubleToInt(glue, leftDouble);
623 opNumber1 = GetInt32OfTInt(right);
624 Jump(&calculate);
625 }
626 Bind(&rightIsDouble);
627 {
628 GateRef rightDouble = GetDoubleOfTDouble(right);
629 GateRef leftDouble = GetDoubleOfTDouble(left);
630 opNumber0 = DoubleToInt(glue, leftDouble);
631 opNumber1 = DoubleToInt(glue, rightDouble);
632 Jump(&calculate);
633 }
634 }
635 }
636 }
637 // slow path
638 Bind(&leftNotNumberOrRightNotNumber);
639 {
640 result = CallRuntime(glue, RTSTUB_ID(Shl2), { left, right });
641 Jump(&exit);
642 }
643 Bind(&calculate);
644 {
645 GateRef shift = Int32And(*opNumber1, Int32(0x1f));
646 GateRef val = Int32LSL(*opNumber0, shift);
647 result = IntToTaggedPtr(val);
648 Jump(&exit);
649 }
650 Bind(&exit);
651 auto ret = *result;
652 env->SubCfgExit();
653 return ret;
654 }
655
Shr(GateRef glue,GateRef left,GateRef right)656 GateRef OperationsStubBuilder::Shr(GateRef glue, GateRef left, GateRef right)
657 {
658 auto env = GetEnvironment();
659 Label entry(env);
660 env->SubCfgEntry(&entry);
661 Label exit(env);
662
663 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
664 DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0));
665 DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0));
666
667 Label doShr(env);
668 Label overflow(env);
669 Label notOverflow(env);
670 Label leftIsNumber(env);
671 Label leftNotNumberOrRightNotNumber(env);
672 Branch(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
673 Bind(&leftIsNumber);
674 {
675 Label rightIsNumber(env);
676 Branch(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
677 Bind(&rightIsNumber);
678 {
679 Label leftIsInt(env);
680 Label leftIsDouble(env);
681 Branch(TaggedIsInt(left), &leftIsInt, &leftIsDouble);
682 Bind(&leftIsInt);
683 {
684 Label rightIsInt(env);
685 Label rightIsDouble(env);
686 Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
687 Bind(&rightIsInt);
688 {
689 opNumber0 = GetInt32OfTInt(left);
690 opNumber1 = GetInt32OfTInt(right);
691 Jump(&doShr);
692 }
693 Bind(&rightIsDouble);
694 {
695 GateRef rightDouble = GetDoubleOfTDouble(right);
696 opNumber0 = GetInt32OfTInt(left);
697 opNumber1 = DoubleToInt(glue, rightDouble);
698 Jump(&doShr);
699 }
700 }
701 Bind(&leftIsDouble);
702 {
703 Label rightIsInt(env);
704 Label rightIsDouble(env);
705 Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
706 Bind(&rightIsInt);
707 {
708 GateRef leftDouble = GetDoubleOfTDouble(left);
709 opNumber0 = DoubleToInt(glue, leftDouble);
710 opNumber1 = GetInt32OfTInt(right);
711 Jump(&doShr);
712 }
713 Bind(&rightIsDouble);
714 {
715 GateRef rightDouble = GetDoubleOfTDouble(right);
716 GateRef leftDouble = GetDoubleOfTDouble(left);
717 opNumber0 = DoubleToInt(glue, leftDouble);
718 opNumber1 = DoubleToInt(glue, rightDouble);
719 Jump(&doShr);
720 }
721 }
722 }
723 }
724 // slow path
725 Bind(&leftNotNumberOrRightNotNumber);
726 {
727 result = CallRuntime(glue, RTSTUB_ID(Shr2), { left, right });
728 Jump(&exit);
729 }
730 Bind(&doShr);
731 {
732 GateRef shift = Int32And(*opNumber1, Int32(0x1f));
733 GateRef val = Int32LSR(*opNumber0, shift);
734 auto condition = Int32UnsignedGreaterThan(val, Int32(INT32_MAX));
735 Branch(condition, &overflow, ¬Overflow);
736 Bind(&overflow);
737 {
738 result = DoubleToTaggedDoublePtr(ChangeUInt32ToFloat64(val));
739 Jump(&exit);
740 }
741 Bind(¬Overflow);
742 {
743 result = IntToTaggedPtr(val);
744 Jump(&exit);
745 }
746 }
747 Bind(&exit);
748 auto ret = *result;
749 env->SubCfgExit();
750 return ret;
751 }
752
Ashr(GateRef glue,GateRef left,GateRef right)753 GateRef OperationsStubBuilder::Ashr(GateRef glue, GateRef left, GateRef right)
754 {
755 auto env = GetEnvironment();
756 Label entry(env);
757 env->SubCfgEntry(&entry);
758 Label exit(env);
759
760 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
761 DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0));
762 DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0));
763
764 Label calculate(env);
765 Label leftIsNumber(env);
766 Label leftNotNumberOrRightNotNumber(env);
767 Branch(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
768 Bind(&leftIsNumber);
769 {
770 Label rightIsNumber(env);
771 Branch(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
772 Bind(&rightIsNumber);
773 {
774 Label leftIsInt(env);
775 Label leftIsDouble(env);
776 Branch(TaggedIsInt(left), &leftIsInt, &leftIsDouble);
777 Bind(&leftIsInt);
778 {
779 Label rightIsInt(env);
780 Label rightIsDouble(env);
781 Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
782 Bind(&rightIsInt);
783 {
784 opNumber0 = GetInt32OfTInt(left);
785 opNumber1 = GetInt32OfTInt(right);
786 Jump(&calculate);
787 }
788 Bind(&rightIsDouble);
789 {
790 GateRef rightDouble = GetDoubleOfTDouble(right);
791 opNumber0 = GetInt32OfTInt(left);
792 opNumber1 = DoubleToInt(glue, rightDouble);
793 Jump(&calculate);
794 }
795 }
796 Bind(&leftIsDouble);
797 {
798 Label rightIsInt(env);
799 Label rightIsDouble(env);
800 Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
801 Bind(&rightIsInt);
802 {
803 GateRef leftDouble = GetDoubleOfTDouble(left);
804 opNumber0 = DoubleToInt(glue, leftDouble);
805 opNumber1 = GetInt32OfTInt(right);
806 Jump(&calculate);
807 }
808 Bind(&rightIsDouble);
809 {
810 GateRef rightDouble = GetDoubleOfTDouble(right);
811 GateRef leftDouble = GetDoubleOfTDouble(left);
812 opNumber0 = DoubleToInt(glue, leftDouble);
813 opNumber1 = DoubleToInt(glue, rightDouble);
814 Jump(&calculate);
815 }
816 }
817 }
818 }
819 // slow path
820 Bind(&leftNotNumberOrRightNotNumber);
821 {
822 result = CallRuntime(glue, RTSTUB_ID(Ashr2), { left, right });
823 Jump(&exit);
824 }
825 Bind(&calculate);
826 {
827 GateRef shift = Int32And(*opNumber1, Int32(0x1f));
828 GateRef val = Int32ASR(*opNumber0, shift);
829 result = IntToTaggedPtr(val);
830 Jump(&exit);
831 }
832 Bind(&exit);
833 auto ret = *result;
834 env->SubCfgExit();
835 return ret;
836 }
837
And(GateRef glue,GateRef left,GateRef right)838 GateRef OperationsStubBuilder::And(GateRef glue, GateRef left, GateRef right)
839 {
840 auto env = GetEnvironment();
841 Label entry(env);
842 env->SubCfgEntry(&entry);
843 Label exit(env);
844
845 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
846 DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0));
847 DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0));
848
849 Label calculate(env);
850 Label leftIsNumber(env);
851 Label leftNotNumberOrRightNotNumber(env);
852 Branch(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
853 Bind(&leftIsNumber);
854 {
855 Label rightIsNumber(env);
856 Branch(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
857 Bind(&rightIsNumber);
858 {
859 Label leftIsInt(env);
860 Label leftIsDouble(env);
861 Branch(TaggedIsInt(left), &leftIsInt, &leftIsDouble);
862 Bind(&leftIsInt);
863 {
864 Label rightIsInt(env);
865 Label rightIsDouble(env);
866 Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
867 Bind(&rightIsInt);
868 {
869 opNumber0 = GetInt32OfTInt(left);
870 opNumber1 = GetInt32OfTInt(right);
871 Jump(&calculate);
872 }
873 Bind(&rightIsDouble);
874 {
875 opNumber0 = GetInt32OfTInt(left);
876 GateRef rightDouble = GetDoubleOfTDouble(right);
877 opNumber1 = DoubleToInt(glue, rightDouble);
878 Jump(&calculate);
879 }
880 }
881 Bind(&leftIsDouble);
882 {
883 Label rightIsInt(env);
884 Label rightIsDouble(env);
885 Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
886 Bind(&rightIsInt);
887 {
888 GateRef leftDouble = GetDoubleOfTDouble(left);
889 opNumber0 = DoubleToInt(glue, leftDouble);
890 opNumber1 = GetInt32OfTInt(right);
891 Jump(&calculate);
892 }
893 Bind(&rightIsDouble);
894 {
895 GateRef rightDouble = GetDoubleOfTDouble(right);
896 GateRef leftDouble = GetDoubleOfTDouble(left);
897 opNumber0 = DoubleToInt(glue, leftDouble);
898 opNumber1 = DoubleToInt(glue, rightDouble);
899 Jump(&calculate);
900 }
901 }
902 }
903 }
904 // slow path
905 Bind(&leftNotNumberOrRightNotNumber);
906 {
907 result = CallRuntime(glue, RTSTUB_ID(And2), { left, right });
908 Jump(&exit);
909 }
910 Bind(&calculate);
911 {
912 GateRef val = Int32And(*opNumber0, *opNumber1);
913 result = IntToTaggedPtr(val);
914 Jump(&exit);
915 }
916 Bind(&exit);
917 auto ret = *result;
918 env->SubCfgExit();
919 return ret;
920 }
921
Or(GateRef glue,GateRef left,GateRef right)922 GateRef OperationsStubBuilder::Or(GateRef glue, GateRef left, GateRef right)
923 {
924 auto env = GetEnvironment();
925 Label entry(env);
926 env->SubCfgEntry(&entry);
927 Label exit(env);
928
929 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
930 DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0));
931 DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0));
932
933 Label calculate(env);
934 Label leftIsNumber(env);
935 Label leftNotNumberOrRightNotNumber(env);
936 Branch(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
937 Bind(&leftIsNumber);
938 {
939 Label rightIsNumber(env);
940 Branch(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
941 Bind(&rightIsNumber);
942 {
943 Label leftIsInt(env);
944 Label leftIsDouble(env);
945 Branch(TaggedIsInt(left), &leftIsInt, &leftIsDouble);
946 Bind(&leftIsInt);
947 {
948 Label rightIsInt(env);
949 Label rightIsDouble(env);
950 Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
951 Bind(&rightIsInt);
952 {
953 opNumber0 = GetInt32OfTInt(left);
954 opNumber1 = GetInt32OfTInt(right);
955 Jump(&calculate);
956 }
957 Bind(&rightIsDouble);
958 {
959 GateRef rightDouble = GetDoubleOfTDouble(right);
960 opNumber0 = GetInt32OfTInt(left);
961 opNumber1 = DoubleToInt(glue, rightDouble);
962 Jump(&calculate);
963 }
964 }
965 Bind(&leftIsDouble);
966 {
967 Label rightIsInt(env);
968 Label rightIsDouble(env);
969 Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
970 Bind(&rightIsInt);
971 {
972 GateRef leftDouble = GetDoubleOfTDouble(left);
973 opNumber0 = DoubleToInt(glue, leftDouble);
974 opNumber1 = GetInt32OfTInt(right);
975 Jump(&calculate);
976 }
977 Bind(&rightIsDouble);
978 {
979 GateRef rightDouble = GetDoubleOfTDouble(right);
980 GateRef leftDouble = GetDoubleOfTDouble(left);
981 opNumber0 = DoubleToInt(glue, leftDouble);
982 opNumber1 = DoubleToInt(glue, rightDouble);
983 Jump(&calculate);
984 }
985 }
986 }
987 }
988 // slow path
989 Bind(&leftNotNumberOrRightNotNumber);
990 {
991 result = CallRuntime(glue, RTSTUB_ID(Or2), { left, right });
992 Jump(&exit);
993 }
994 Bind(&calculate);
995 {
996 GateRef val = Int32Or(*opNumber0, *opNumber1);
997 result = IntToTaggedPtr(val);
998 Jump(&exit);
999 }
1000 Bind(&exit);
1001 auto ret = *result;
1002 env->SubCfgExit();
1003 return ret;
1004 }
1005
Xor(GateRef glue,GateRef left,GateRef right)1006 GateRef OperationsStubBuilder::Xor(GateRef glue, GateRef left, GateRef right)
1007 {
1008 auto env = GetEnvironment();
1009 Label entry(env);
1010 env->SubCfgEntry(&entry);
1011 Label exit(env);
1012
1013 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
1014 DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0));
1015 DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0));
1016
1017 Label calculate(env);
1018 Label leftIsNumber(env);
1019 Label leftNotNumberOrRightNotNumber(env);
1020 Branch(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
1021 Bind(&leftIsNumber);
1022 {
1023 Label rightIsNumber(env);
1024 Branch(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
1025 Bind(&rightIsNumber);
1026 {
1027 Label leftIsInt(env);
1028 Label leftIsDouble(env);
1029 Branch(TaggedIsInt(left), &leftIsInt, &leftIsDouble);
1030 Bind(&leftIsInt);
1031 {
1032 Label rightIsInt(env);
1033 Label rightIsDouble(env);
1034 Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
1035 Bind(&rightIsInt);
1036 {
1037 opNumber0 = GetInt32OfTInt(left);
1038 opNumber1 = GetInt32OfTInt(right);
1039 Jump(&calculate);
1040 }
1041 Bind(&rightIsDouble);
1042 {
1043 GateRef rightDouble = GetDoubleOfTDouble(right);
1044 opNumber0 = GetInt32OfTInt(left);
1045 opNumber1 = DoubleToInt(glue, rightDouble);
1046 Jump(&calculate);
1047 }
1048 }
1049 Bind(&leftIsDouble);
1050 {
1051 Label rightIsInt(env);
1052 Label rightIsDouble(env);
1053 Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
1054 Bind(&rightIsInt);
1055 {
1056 GateRef leftDouble = GetDoubleOfTDouble(left);
1057 opNumber0 = DoubleToInt(glue, leftDouble);
1058 opNumber1 = GetInt32OfTInt(right);
1059 Jump(&calculate);
1060 }
1061 Bind(&rightIsDouble);
1062 {
1063 GateRef rightDouble = GetDoubleOfTDouble(right);
1064 GateRef leftDouble = GetDoubleOfTDouble(left);
1065 opNumber0 = DoubleToInt(glue, leftDouble);
1066 opNumber1 = DoubleToInt(glue, rightDouble);
1067 Jump(&calculate);
1068 }
1069 }
1070 }
1071 }
1072 // slow path
1073 Bind(&leftNotNumberOrRightNotNumber);
1074 {
1075 result = CallRuntime(glue, RTSTUB_ID(Xor2), { left, right });
1076 Jump(&exit);
1077 }
1078 Bind(&calculate);
1079 {
1080 GateRef val = Int32Xor(*opNumber0, *opNumber1);
1081 result = IntToTaggedPtr(val);
1082 Jump(&exit);
1083 }
1084 Bind(&exit);
1085 auto ret = *result;
1086 env->SubCfgExit();
1087 return ret;
1088 }
1089
Inc(GateRef glue,GateRef value)1090 GateRef OperationsStubBuilder::Inc(GateRef glue, GateRef value)
1091 {
1092 auto env = GetEnvironment();
1093 Label entry(env);
1094 env->SubCfgEntry(&entry);
1095 Label exit(env);
1096
1097 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
1098 Label valueIsInt(env);
1099 Label valueNotInt(env);
1100 Label slowPath(env);
1101 Branch(TaggedIsInt(value), &valueIsInt, &valueNotInt);
1102 Bind(&valueIsInt);
1103 {
1104 GateRef valueInt = GetInt32OfTInt(value);
1105 Label valueNoOverflow(env);
1106 Branch(Int32Equal(valueInt, Int32(INT32_MAX)), &valueNotInt, &valueNoOverflow);
1107 Bind(&valueNoOverflow);
1108 {
1109 result = IntToTaggedPtr(Int32Add(valueInt, Int32(1)));
1110 Jump(&exit);
1111 }
1112 }
1113 Bind(&valueNotInt);
1114 {
1115 Label valueIsDouble(env);
1116 Branch(TaggedIsDouble(value), &valueIsDouble, &slowPath);
1117 Bind(&valueIsDouble);
1118 {
1119 GateRef valueDouble = GetDoubleOfTDouble(value);
1120 result = DoubleToTaggedDoublePtr(DoubleAdd(valueDouble, Double(1.0)));
1121 Jump(&exit);
1122 }
1123 }
1124 Bind(&slowPath);
1125 {
1126 result = CallRuntime(glue, RTSTUB_ID(Inc), { value });
1127 Jump(&exit);
1128 }
1129 Bind(&exit);
1130 auto ret = *result;
1131 env->SubCfgExit();
1132 return ret;
1133 }
1134
Dec(GateRef glue,GateRef value)1135 GateRef OperationsStubBuilder::Dec(GateRef glue, GateRef value)
1136 {
1137 auto env = GetEnvironment();
1138 Label entry(env);
1139 env->SubCfgEntry(&entry);
1140 Label exit(env);
1141
1142 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
1143 Label valueIsInt(env);
1144 Label valueNotInt(env);
1145 Label slowPath(env);
1146 Branch(TaggedIsInt(value), &valueIsInt, &valueNotInt);
1147 Bind(&valueIsInt);
1148 {
1149 GateRef valueInt = GetInt32OfTInt(value);
1150 Label valueNoOverflow(env);
1151 Branch(Int32Equal(valueInt, Int32(INT32_MIN)), &valueNotInt, &valueNoOverflow);
1152 Bind(&valueNoOverflow);
1153 {
1154 result = IntToTaggedPtr(Int32Sub(valueInt, Int32(1)));
1155 Jump(&exit);
1156 }
1157 }
1158 Bind(&valueNotInt);
1159 {
1160 Label valueIsDouble(env);
1161 Branch(TaggedIsDouble(value), &valueIsDouble, &slowPath);
1162 Bind(&valueIsDouble);
1163 {
1164 GateRef valueDouble = GetDoubleOfTDouble(value);
1165 result = DoubleToTaggedDoublePtr(DoubleSub(valueDouble, Double(1.0)));
1166 Jump(&exit);
1167 }
1168 }
1169 Bind(&slowPath);
1170 {
1171 result = CallRuntime(glue, RTSTUB_ID(Dec), { value });
1172 Jump(&exit);
1173 }
1174
1175 Bind(&exit);
1176 auto ret = *result;
1177 env->SubCfgExit();
1178 return ret;
1179 }
1180
Neg(GateRef glue,GateRef value)1181 GateRef OperationsStubBuilder::Neg(GateRef glue, GateRef value)
1182 {
1183 auto env = GetEnvironment();
1184 Label entry(env);
1185 env->SubCfgEntry(&entry);
1186 Label exit(env);
1187
1188 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
1189 Label valueIsInt(env);
1190 Label valueNotInt(env);
1191 Branch(TaggedIsInt(value), &valueIsInt, &valueNotInt);
1192 Bind(&valueIsInt);
1193 {
1194 GateRef valueInt = GetInt32OfTInt(value);
1195 Label valueIsZero(env);
1196 Label valueNotZero(env);
1197 Branch(Int32Equal(valueInt, Int32(0)), &valueIsZero, &valueNotZero);
1198 Bind(&valueIsZero);
1199 {
1200 result = DoubleToTaggedDoublePtr(Double(-0.0));
1201 Jump(&exit);
1202 }
1203 Bind(&valueNotZero);
1204 {
1205 Label valueIsInt32Min(env);
1206 Label valueNotInt32Min(env);
1207 Branch(Int32Equal(valueInt, Int32(INT32_MIN)), &valueIsInt32Min, &valueNotInt32Min);
1208 Bind(&valueIsInt32Min);
1209 {
1210 result = DoubleToTaggedDoublePtr(Double(-static_cast<double>(INT32_MIN)));
1211 Jump(&exit);
1212 }
1213 Bind(&valueNotInt32Min);
1214 {
1215 result = IntToTaggedPtr(Int32Sub(Int32(0), valueInt));
1216 Jump(&exit);
1217 }
1218 }
1219 }
1220 Bind(&valueNotInt);
1221 {
1222 Label valueIsDouble(env);
1223 Label valueNotDouble(env);
1224 Branch(TaggedIsDouble(value), &valueIsDouble, &valueNotDouble);
1225 Bind(&valueIsDouble);
1226 {
1227 GateRef valueDouble = GetDoubleOfTDouble(value);
1228 result = DoubleToTaggedDoublePtr(DoubleSub(Double(0), valueDouble));
1229 Jump(&exit);
1230 }
1231 Bind(&valueNotDouble);
1232 {
1233 // slow path
1234 result = CallRuntime(glue, RTSTUB_ID(Neg), { value });
1235 Jump(&exit);
1236 }
1237 }
1238 Bind(&exit);
1239 auto ret = *result;
1240 env->SubCfgExit();
1241 return ret;
1242 }
1243
Not(GateRef glue,GateRef value)1244 GateRef OperationsStubBuilder::Not(GateRef glue, GateRef value)
1245 {
1246 auto env = GetEnvironment();
1247 Label entry(env);
1248 env->SubCfgEntry(&entry);
1249 Label exit(env);
1250
1251 DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
1252 Label numberIsInt(env);
1253 Label numberNotInt(env);
1254 Branch(TaggedIsInt(value), &numberIsInt, &numberNotInt);
1255 Bind(&numberIsInt);
1256 {
1257 GateRef valueInt = GetInt32OfTInt(value);
1258 result = IntToTaggedPtr(Int32Not(valueInt));
1259 Jump(&exit);
1260 }
1261 Bind(&numberNotInt);
1262 {
1263 Label numberIsDouble(env);
1264 Label numberNotDouble(env);
1265 Branch(TaggedIsDouble(value), &numberIsDouble, &numberNotDouble);
1266 Bind(&numberIsDouble);
1267 {
1268 GateRef valueDouble = GetDoubleOfTDouble(value);
1269 result = IntToTaggedPtr(Int32Not(DoubleToInt(glue, valueDouble)));
1270 Jump(&exit);
1271 }
1272 Bind(&numberNotDouble);
1273 {
1274 // slow path
1275 result = CallRuntime(glue, RTSTUB_ID(Not), { value });
1276 Jump(&exit);
1277 }
1278 }
1279 Bind(&exit);
1280 auto ret = *result;
1281 env->SubCfgExit();
1282 return ret;
1283 }
1284 } // namespace panda::ecmascript::kungfu
1285