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