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